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

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

Issue 2890463004: [inspector] Refactor inspector test (Closed)
Patch Set: works 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
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 #if !defined(_WIN32) && !defined(_WIN64) 5 #if !defined(_WIN32) && !defined(_WIN64)
6 #include <unistd.h> // NOLINT 6 #include <unistd.h> // NOLINT
7 #endif // !defined(_WIN32) && !defined(_WIN64) 7 #endif // !defined(_WIN32) && !defined(_WIN64)
8 8
9 #include <locale.h> 9 #include <locale.h>
10 10
11 #include "include/libplatform/libplatform.h" 11 #include "include/libplatform/libplatform.h"
12 #include "include/v8.h" 12 #include "include/v8.h"
13 13
14 #include "src/base/platform/platform.h" 14 #include "src/base/platform/platform.h"
15 #include "src/conversions.h"
15 #include "src/flags.h" 16 #include "src/flags.h"
16 #include "src/inspector/test-interface.h" 17 #include "src/inspector/test-interface.h"
17 #include "src/utils.h" 18 #include "src/utils.h"
18 #include "src/vector.h" 19 #include "src/vector.h"
19 20
20 #include "test/inspector/inspector-impl.h" 21 #include "test/inspector/inspector-impl.h"
21 #include "test/inspector/task-runner.h" 22 #include "test/inspector/task-runner.h"
22 23
23 namespace { 24 namespace {
24 25
(...skipping 19 matching lines...) Expand all
44 v8::internal::Vector<uint16_t>::New(str->Length()); 45 v8::internal::Vector<uint16_t>::New(str->Length());
45 str->Write(buffer.start(), 0, str->Length()); 46 str->Write(buffer.start(), 0, str->Length());
46 return buffer; 47 return buffer;
47 } 48 }
48 49
49 v8::Local<v8::String> ToV8String(v8::Isolate* isolate, const char* str) { 50 v8::Local<v8::String> ToV8String(v8::Isolate* isolate, const char* str) {
50 return v8::String::NewFromUtf8(isolate, str, v8::NewStringType::kNormal) 51 return v8::String::NewFromUtf8(isolate, str, v8::NewStringType::kNormal)
51 .ToLocalChecked(); 52 .ToLocalChecked();
52 } 53 }
53 54
55 v8::internal::Vector<uint16_t> ToVector(
56 const v8_inspector::StringView& string) {
57 v8::internal::Vector<uint16_t> buffer =
58 v8::internal::Vector<uint16_t>::New(static_cast<int>(string.length()));
59 for (size_t i = 0; i < string.length(); i++) {
60 if (string.is8Bit())
61 buffer[i] = string.characters8()[i];
62 else
63 buffer[i] = string.characters16()[i];
64 }
65 return buffer;
66 }
67
68 class CreateContextGroupTask : public TaskRunner::Task {
69 public:
70 CreateContextGroupTask(v8::base::Semaphore* ready_semaphore,
71 int* context_group_id)
72 : ready_semaphore_(ready_semaphore),
73 context_group_id_(context_group_id) {}
74 virtual ~CreateContextGroupTask() = default;
75 bool is_inspector_task() final { return true; }
76
77 private:
78 void Run() override {
79 *context_group_id_ = data()->CreateContextGroup();
80 if (ready_semaphore_) ready_semaphore_->Signal();
81 }
82
83 v8::base::Semaphore* ready_semaphore_;
84 int* context_group_id_;
85 };
86
87 class ConnectSessionTask : public TaskRunner::Task {
88 public:
89 ConnectSessionTask(v8::base::Semaphore* ready_semaphore, int context_group_id,
90 const v8::internal::Vector<uint16_t>& state,
91 int* session_id)
92 : ready_semaphore_(ready_semaphore),
93 context_group_id_(context_group_id),
94 state_(state),
95 session_id_(session_id) {}
96 virtual ~ConnectSessionTask() = default;
97 bool is_inspector_task() final { return true; }
98
99 private:
100 void Run() override {
101 v8_inspector::StringView state(state_.start(), state_.length());
102 *session_id_ =
103 data()->inspector()->ConnectSession(context_group_id_, state);
104 if (ready_semaphore_) ready_semaphore_->Signal();
105 }
106
107 v8::base::Semaphore* ready_semaphore_;
108 int context_group_id_;
109 const v8::internal::Vector<uint16_t>& state_;
110 int* session_id_;
111 };
112
113 class DisconnectSessionTask : public TaskRunner::Task {
114 public:
115 DisconnectSessionTask(v8::base::Semaphore* ready_semaphore, int session_id,
116 v8::internal::Vector<uint16_t>* state)
117 : ready_semaphore_(ready_semaphore),
118 session_id_(session_id),
119 state_(state) {}
120 virtual ~DisconnectSessionTask() = default;
121 bool is_inspector_task() final { return true; }
122
123 private:
124 void Run() override {
125 std::unique_ptr<v8_inspector::StringBuffer> state =
126 data()->inspector()->DisconnectSession(session_id_);
127 *state_ = ToVector(state->string());
128 if (ready_semaphore_) ready_semaphore_->Signal();
129 }
130
131 v8::base::Semaphore* ready_semaphore_;
132 int session_id_;
133 v8::internal::Vector<uint16_t>* state_;
134 };
135
136 class SendMessageToBackendTask : public TaskRunner::Task {
137 public:
138 explicit SendMessageToBackendTask(
139 int session_id, const v8::internal::Vector<uint16_t>& message)
140 : session_id_(session_id), message_(message) {}
141 bool is_inspector_task() final { return true; }
142
143 private:
144 void Run() override {
145 v8_inspector::StringView message_view(message_.start(), message_.length());
146 data()->inspector()->SendMessage(session_id_, message_view);
147 }
148
149 int session_id_;
150 v8::internal::Vector<uint16_t> message_;
151 };
152
153 class SchedulePauseOnNextStatementTask : public TaskRunner::Task {
154 public:
155 SchedulePauseOnNextStatementTask(
156 v8::base::Semaphore* ready_semaphore, int context_group_id,
157 const v8::internal::Vector<uint16_t>& reason,
158 const v8::internal::Vector<uint16_t>& details)
159 : ready_semaphore_(ready_semaphore),
160 context_group_id_(context_group_id),
161 reason_(reason),
162 details_(details) {}
163 virtual ~SchedulePauseOnNextStatementTask() = default;
164 bool is_inspector_task() final { return true; }
165
166 private:
167 void Run() override {
168 v8_inspector::StringView reason(reason_.start(), reason_.length());
169 v8_inspector::StringView details(details_.start(), details_.length());
170 data()->inspector()->SchedulePauseOnNextStatement(context_group_id_, reason,
171 details);
172 if (ready_semaphore_) ready_semaphore_->Signal();
173 }
174
175 v8::base::Semaphore* ready_semaphore_;
176 int context_group_id_;
177 const v8::internal::Vector<uint16_t>& reason_;
178 const v8::internal::Vector<uint16_t>& details_;
179 };
180
181 class CancelPauseOnNextStatementTask : public TaskRunner::Task {
182 public:
183 CancelPauseOnNextStatementTask(v8::base::Semaphore* ready_semaphore,
184 int context_group_id)
185 : ready_semaphore_(ready_semaphore),
186 context_group_id_(context_group_id) {}
187 virtual ~CancelPauseOnNextStatementTask() = default;
188 bool is_inspector_task() final { return true; }
189
190 private:
191 void Run() override {
192 data()->inspector()->CancelPauseOnNextStatement(context_group_id_);
193 if (ready_semaphore_) ready_semaphore_->Signal();
194 }
195
196 v8::base::Semaphore* ready_semaphore_;
197 int context_group_id_;
198 };
199
54 class UtilsExtension : public IsolateData::SetupGlobalTask { 200 class UtilsExtension : public IsolateData::SetupGlobalTask {
55 public: 201 public:
56 ~UtilsExtension() override = default; 202 ~UtilsExtension() override = default;
57 void Run(v8::Isolate* isolate, 203 void Run(v8::Isolate* isolate,
58 v8::Local<v8::ObjectTemplate> global) override { 204 v8::Local<v8::ObjectTemplate> global) override {
59 v8::Local<v8::ObjectTemplate> utils = v8::ObjectTemplate::New(isolate); 205 v8::Local<v8::ObjectTemplate> utils = v8::ObjectTemplate::New(isolate);
60 utils->Set(ToV8String(isolate, "print"), 206 utils->Set(ToV8String(isolate, "print"),
61 v8::FunctionTemplate::New(isolate, &UtilsExtension::Print)); 207 v8::FunctionTemplate::New(isolate, &UtilsExtension::Print));
62 utils->Set(ToV8String(isolate, "quit"), 208 utils->Set(ToV8String(isolate, "quit"),
63 v8::FunctionTemplate::New(isolate, &UtilsExtension::Quit)); 209 v8::FunctionTemplate::New(isolate, &UtilsExtension::Quit));
(...skipping 11 matching lines...) Expand all
75 isolate, &UtilsExtension::SetCurrentTimeMSForTest)); 221 isolate, &UtilsExtension::SetCurrentTimeMSForTest));
76 utils->Set(ToV8String(isolate, "setMemoryInfoForTest"), 222 utils->Set(ToV8String(isolate, "setMemoryInfoForTest"),
77 v8::FunctionTemplate::New( 223 v8::FunctionTemplate::New(
78 isolate, &UtilsExtension::SetMemoryInfoForTest)); 224 isolate, &UtilsExtension::SetMemoryInfoForTest));
79 utils->Set(ToV8String(isolate, "schedulePauseOnNextStatement"), 225 utils->Set(ToV8String(isolate, "schedulePauseOnNextStatement"),
80 v8::FunctionTemplate::New( 226 v8::FunctionTemplate::New(
81 isolate, &UtilsExtension::SchedulePauseOnNextStatement)); 227 isolate, &UtilsExtension::SchedulePauseOnNextStatement));
82 utils->Set(ToV8String(isolate, "cancelPauseOnNextStatement"), 228 utils->Set(ToV8String(isolate, "cancelPauseOnNextStatement"),
83 v8::FunctionTemplate::New( 229 v8::FunctionTemplate::New(
84 isolate, &UtilsExtension::CancelPauseOnNextStatement)); 230 isolate, &UtilsExtension::CancelPauseOnNextStatement));
85 utils->Set(ToV8String(isolate, "reconnect"),
86 v8::FunctionTemplate::New(isolate, &UtilsExtension::Reconnect));
87 utils->Set(ToV8String(isolate, "disconnect"),
88 v8::FunctionTemplate::New(isolate, &UtilsExtension::Disconnect));
89 utils->Set(ToV8String(isolate, "setLogConsoleApiMessageCalls"), 231 utils->Set(ToV8String(isolate, "setLogConsoleApiMessageCalls"),
90 v8::FunctionTemplate::New( 232 v8::FunctionTemplate::New(
91 isolate, &UtilsExtension::SetLogConsoleApiMessageCalls)); 233 isolate, &UtilsExtension::SetLogConsoleApiMessageCalls));
92 utils->Set(ToV8String(isolate, "createContextGroup"), 234 utils->Set(ToV8String(isolate, "createContextGroup"),
93 v8::FunctionTemplate::New(isolate, 235 v8::FunctionTemplate::New(isolate,
94 &UtilsExtension::CreateContextGroup)); 236 &UtilsExtension::CreateContextGroup));
237 utils->Set(
238 ToV8String(isolate, "connectSession"),
239 v8::FunctionTemplate::New(isolate, &UtilsExtension::ConnectSession));
240 utils->Set(
241 ToV8String(isolate, "disconnectSession"),
242 v8::FunctionTemplate::New(isolate, &UtilsExtension::DisconnectSession));
243 utils->Set(ToV8String(isolate, "sendMessageToBackend"),
244 v8::FunctionTemplate::New(
245 isolate, &UtilsExtension::SendMessageToBackend));
95 global->Set(ToV8String(isolate, "utils"), utils); 246 global->Set(ToV8String(isolate, "utils"), utils);
96 } 247 }
97 248
98 static void set_backend_task_runner(TaskRunner* runner) { 249 static void set_backend_task_runner(TaskRunner* runner) {
99 backend_runner_ = runner; 250 backend_runner_ = runner;
100 } 251 }
101 252
102 static void set_inspector_client(InspectorClientImpl* client) {
103 inspector_client_ = client;
104 }
105
106 private: 253 private:
107 static TaskRunner* backend_runner_; 254 static TaskRunner* backend_runner_;
108 static InspectorClientImpl* inspector_client_;
109 255
110 static void Print(const v8::FunctionCallbackInfo<v8::Value>& args) { 256 static void Print(const v8::FunctionCallbackInfo<v8::Value>& args) {
111 for (int i = 0; i < args.Length(); i++) { 257 for (int i = 0; i < args.Length(); i++) {
112 v8::HandleScope handle_scope(args.GetIsolate()); 258 v8::HandleScope handle_scope(args.GetIsolate());
113 if (i != 0) { 259 if (i != 0) {
114 printf(" "); 260 printf(" ");
115 } 261 }
116 262
117 // Explicitly catch potential exceptions in toString(). 263 // Explicitly catch potential exceptions in toString().
118 v8::TryCatch try_catch(args.GetIsolate()); 264 v8::TryCatch try_catch(args.GetIsolate());
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 } 328 }
183 } 329 }
184 330
185 static void Load(const v8::FunctionCallbackInfo<v8::Value>& args) { 331 static void Load(const v8::FunctionCallbackInfo<v8::Value>& args) {
186 if (args.Length() != 1 || !args[0]->IsString()) { 332 if (args.Length() != 1 || !args[0]->IsString()) {
187 fprintf(stderr, "Internal error: load gets one string argument."); 333 fprintf(stderr, "Internal error: load gets one string argument.");
188 Exit(); 334 Exit();
189 } 335 }
190 v8::internal::Vector<const char> chars; 336 v8::internal::Vector<const char> chars;
191 v8::Isolate* isolate = args.GetIsolate(); 337 v8::Isolate* isolate = args.GetIsolate();
338 v8::Local<v8::Context> context = isolate->GetCurrentContext();
339 IsolateData* data = IsolateData::FromContext(context);
340 int context_group_id = data->GetContextGroupId(context);
192 if (ReadFile(isolate, args[0], &chars)) { 341 if (ReadFile(isolate, args[0], &chars)) {
193 ExecuteStringTask(chars).RunOnTaskRunner( 342 ExecuteStringTask(chars, context_group_id).RunOnIsolate(data);
194 IsolateData::FromContext(isolate->GetCurrentContext())
195 ->task_runner());
196 } 343 }
197 } 344 }
198 345
199 static void CompileAndRunWithOrigin( 346 static void CompileAndRunWithOrigin(
200 const v8::FunctionCallbackInfo<v8::Value>& args) { 347 const v8::FunctionCallbackInfo<v8::Value>& args) {
201 if (args.Length() != 5 || !args[0]->IsString() || !args[1]->IsString() || 348 if (args.Length() != 6 || !args[0]->IsInt32() || !args[1]->IsString() ||
202 !args[2]->IsInt32() || !args[3]->IsInt32() || !args[4]->IsBoolean()) { 349 !args[2]->IsString() || !args[3]->IsInt32() || !args[4]->IsInt32() ||
350 !args[5]->IsBoolean()) {
203 fprintf(stderr, 351 fprintf(stderr,
204 "Internal error: compileAndRunWithOrigin(source, name, line, " 352 "Internal error: compileAndRunWithOrigin(context_group_id, "
353 "source, name, line, "
205 "column, is_module)."); 354 "column, is_module).");
206 Exit(); 355 Exit();
207 } 356 }
208 357
209 backend_runner_->Append(new ExecuteStringTask( 358 backend_runner_->Append(new ExecuteStringTask(
210 ToVector(args[0].As<v8::String>()), args[1].As<v8::String>(), 359 nullptr, args[0].As<v8::Int32>()->Value(), nullptr,
211 args[2].As<v8::Int32>(), args[3].As<v8::Int32>(), 360 ToVector(args[1].As<v8::String>()), args[2].As<v8::String>(),
212 args[4].As<v8::Boolean>(), nullptr, nullptr)); 361 args[3].As<v8::Int32>(), args[4].As<v8::Int32>(),
362 args[5].As<v8::Boolean>()));
213 } 363 }
214 364
215 static void SetCurrentTimeMSForTest( 365 static void SetCurrentTimeMSForTest(
216 const v8::FunctionCallbackInfo<v8::Value>& args) { 366 const v8::FunctionCallbackInfo<v8::Value>& args) {
217 if (args.Length() != 1 || !args[0]->IsNumber()) { 367 if (args.Length() != 1 || !args[0]->IsNumber()) {
218 fprintf(stderr, "Internal error: setCurrentTimeMSForTest(time)."); 368 fprintf(stderr, "Internal error: setCurrentTimeMSForTest(time).");
219 Exit(); 369 Exit();
220 } 370 }
221 inspector_client_->setCurrentTimeMSForTest( 371 backend_runner_->data()->inspector()->SetCurrentTimeMSForTest(
222 args[0].As<v8::Number>()->Value()); 372 args[0].As<v8::Number>()->Value());
223 } 373 }
224 374
225 static void SetMemoryInfoForTest( 375 static void SetMemoryInfoForTest(
226 const v8::FunctionCallbackInfo<v8::Value>& args) { 376 const v8::FunctionCallbackInfo<v8::Value>& args) {
227 if (args.Length() != 1) { 377 if (args.Length() != 1) {
228 fprintf(stderr, "Internal error: setMemoryInfoForTest(value)."); 378 fprintf(stderr, "Internal error: setMemoryInfoForTest(value).");
229 Exit(); 379 Exit();
230 } 380 }
231 inspector_client_->setMemoryInfoForTest(args[0]); 381 backend_runner_->data()->inspector()->SetMemoryInfoForTest(args[0]);
232 } 382 }
233 383
234 static void SchedulePauseOnNextStatement( 384 static void SchedulePauseOnNextStatement(
235 const v8::FunctionCallbackInfo<v8::Value>& args) { 385 const v8::FunctionCallbackInfo<v8::Value>& args) {
236 if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsString()) { 386 if (args.Length() != 3 || !args[0]->IsInt32() || !args[1]->IsString() ||
237 fprintf( 387 !args[2]->IsString()) {
238 stderr, 388 fprintf(stderr,
239 "Internal error: schedulePauseOnNextStatement('reason', 'details')."); 389 "Internal error: schedulePauseOnNextStatement(context_group_id, "
390 "'reason', 'details').");
240 Exit(); 391 Exit();
241 } 392 }
242 v8::internal::Vector<uint16_t> reason = ToVector(args[0].As<v8::String>()); 393 v8::internal::Vector<uint16_t> reason = ToVector(args[1].As<v8::String>());
243 v8_inspector::StringView reason_view(reason.start(), reason.length()); 394 v8::internal::Vector<uint16_t> details = ToVector(args[2].As<v8::String>());
244 v8::internal::Vector<uint16_t> details = ToVector(args[1].As<v8::String>()); 395 v8::base::Semaphore ready_semaphore(0);
245 v8_inspector::StringView details_view(details.start(), details.length()); 396 backend_runner_->Append(new SchedulePauseOnNextStatementTask(
246 inspector_client_->session()->schedulePauseOnNextStatement(reason_view, 397 &ready_semaphore, args[0].As<v8::Int32>()->Value(), reason, details));
247 details_view); 398 ready_semaphore.Wait();
248 } 399 }
249 400
250 static void CancelPauseOnNextStatement( 401 static void CancelPauseOnNextStatement(
251 const v8::FunctionCallbackInfo<v8::Value>& args) { 402 const v8::FunctionCallbackInfo<v8::Value>& args) {
252 if (args.Length() != 0) { 403 if (args.Length() != 1 || !args[0]->IsInt32()) {
253 fprintf(stderr, "Internal error: cancelPauseOnNextStatement()."); 404 fprintf(stderr,
254 Exit(); 405 "Internal error: cancelPauseOnNextStatement(context_group_id).");
255 }
256 inspector_client_->session()->cancelPauseOnNextStatement();
257 }
258
259 static void Reconnect(const v8::FunctionCallbackInfo<v8::Value>& args) {
260 if (args.Length() != 0) {
261 fprintf(stderr, "Internal error: reconnect().");
262 Exit(); 406 Exit();
263 } 407 }
264 v8::base::Semaphore ready_semaphore(0); 408 v8::base::Semaphore ready_semaphore(0);
265 inspector_client_->scheduleReconnect(&ready_semaphore); 409 backend_runner_->Append(new CancelPauseOnNextStatementTask(
266 ready_semaphore.Wait(); 410 &ready_semaphore, args[0].As<v8::Int32>()->Value()));
267 }
268
269 static void Disconnect(const v8::FunctionCallbackInfo<v8::Value>& args) {
270 if (args.Length() != 0) {
271 fprintf(stderr, "Internal error: disconnect().");
272 Exit();
273 }
274 v8::base::Semaphore ready_semaphore(0);
275 inspector_client_->scheduleDisconnect(&ready_semaphore);
276 ready_semaphore.Wait(); 411 ready_semaphore.Wait();
277 } 412 }
278 413
279 static void SetLogConsoleApiMessageCalls( 414 static void SetLogConsoleApiMessageCalls(
280 const v8::FunctionCallbackInfo<v8::Value>& args) { 415 const v8::FunctionCallbackInfo<v8::Value>& args) {
281 if (args.Length() != 1 || !args[0]->IsBoolean()) { 416 if (args.Length() != 1 || !args[0]->IsBoolean()) {
282 fprintf(stderr, "Internal error: setLogConsoleApiMessageCalls(bool)."); 417 fprintf(stderr, "Internal error: setLogConsoleApiMessageCalls(bool).");
283 Exit(); 418 Exit();
284 } 419 }
285 inspector_client_->setLogConsoleApiMessageCalls( 420 backend_runner_->data()->inspector()->SetLogConsoleApiMessageCalls(
286 args[0].As<v8::Boolean>()->Value()); 421 args[0].As<v8::Boolean>()->Value());
287 } 422 }
288 423
289 static void CreateContextGroup( 424 static void CreateContextGroup(
290 const v8::FunctionCallbackInfo<v8::Value>& args); 425 const v8::FunctionCallbackInfo<v8::Value>& args) {
426 if (args.Length() != 0) {
427 fprintf(stderr, "Internal error: createContextGroup().");
428 Exit();
429 }
430 v8::base::Semaphore ready_semaphore(0);
431 int context_group_id = 0;
432 backend_runner_->Append(
433 new CreateContextGroupTask(&ready_semaphore, &context_group_id));
434 ready_semaphore.Wait();
435 args.GetReturnValue().Set(
436 v8::Int32::New(args.GetIsolate(), context_group_id));
437 }
438
439 static void ConnectSession(const v8::FunctionCallbackInfo<v8::Value>& args) {
440 if (args.Length() > 2 || !args[0]->IsInt32() ||
441 (args.Length() == 2 && !args[1]->IsString())) {
442 fprintf(stderr,
443 "Internal error: connectionSession(context_group_id, state=).");
444 Exit();
445 }
446 v8::internal::Vector<uint16_t> state;
447 if (args.Length() == 2) state = ToVector(args[1].As<v8::String>());
448 v8::base::Semaphore ready_semaphore(0);
449 int session_id = 0;
450 backend_runner_->Append(new ConnectSessionTask(
451 &ready_semaphore, args[0].As<v8::Int32>()->Value(), state,
452 &session_id));
453 ready_semaphore.Wait();
454 args.GetReturnValue().Set(v8::Int32::New(args.GetIsolate(), session_id));
455 }
456
457 static void DisconnectSession(
458 const v8::FunctionCallbackInfo<v8::Value>& args) {
459 if (args.Length() != 1 || !args[0]->IsInt32()) {
460 fprintf(stderr, "Internal error: disconnectionSession(session_id).");
461 Exit();
462 }
463 v8::base::Semaphore ready_semaphore(0);
464 v8::internal::Vector<uint16_t> state;
465 backend_runner_->Append(new DisconnectSessionTask(
466 &ready_semaphore, args[0].As<v8::Int32>()->Value(), &state));
467 ready_semaphore.Wait();
468 args.GetReturnValue().Set(
469 v8::String::NewFromTwoByte(args.GetIsolate(), state.start(),
470 v8::NewStringType::kNormal,
471 static_cast<int>(state.size()))
472 .ToLocalChecked());
473 }
474
475 static void SendMessageToBackend(
476 const v8::FunctionCallbackInfo<v8::Value>& args) {
477 if (args.Length() != 2 || !args[0]->IsInt32() || !args[1]->IsString()) {
478 fprintf(stderr,
479 "Internal error: sendMessageToBackend(session_id, message).");
480 Exit();
481 }
482 backend_runner_->Append(new SendMessageToBackendTask(
483 args[0].As<v8::Int32>()->Value(), ToVector(args[1].As<v8::String>())));
484 }
291 }; 485 };
292 486
293 TaskRunner* UtilsExtension::backend_runner_ = nullptr; 487 TaskRunner* UtilsExtension::backend_runner_ = nullptr;
294 InspectorClientImpl* UtilsExtension::inspector_client_ = nullptr;
295 488
296 class SetTimeoutTask : public AsyncTask { 489 class SetTimeoutTask : public AsyncTask {
297 public: 490 public:
298 SetTimeoutTask(v8::Isolate* isolate, v8::Local<v8::Function> function, 491 SetTimeoutTask(IsolateData* data, int context_group_id, const char* task_name,
299 const char* task_name, v8_inspector::V8Inspector* inspector) 492 v8::Local<v8::Function> function)
300 : AsyncTask(task_name, inspector), function_(isolate, function) {} 493 : AsyncTask(data, task_name),
494 function_(data->isolate(), function),
495 context_group_id_(context_group_id) {}
301 virtual ~SetTimeoutTask() {} 496 virtual ~SetTimeoutTask() {}
302 497
303 bool is_inspector_task() final { return false; } 498 bool is_inspector_task() final { return false; }
304 499
305 private: 500 private:
306 void AsyncRun() override { 501 void AsyncRun() override {
307 v8::MicrotasksScope microtasks_scope(isolate(), 502 v8::MicrotasksScope microtasks_scope(isolate(),
308 v8::MicrotasksScope::kRunMicrotasks); 503 v8::MicrotasksScope::kRunMicrotasks);
309 v8::HandleScope handle_scope(isolate()); 504 v8::HandleScope handle_scope(isolate());
310 v8::Local<v8::Context> context = default_context(); 505 v8::Local<v8::Context> context = data()->GetContext(context_group_id_);
311 v8::Context::Scope context_scope(context); 506 v8::Context::Scope context_scope(context);
312 507
313 v8::Local<v8::Function> function = function_.Get(isolate()); 508 v8::Local<v8::Function> function = function_.Get(isolate());
314 v8::MaybeLocal<v8::Value> result; 509 v8::MaybeLocal<v8::Value> result;
315 result = function->Call(context, context->Global(), 0, nullptr); 510 result = function->Call(context, context->Global(), 0, nullptr);
316 } 511 }
317 512
318 v8::Global<v8::Function> function_; 513 v8::Global<v8::Function> function_;
514 int context_group_id_;
319 }; 515 };
320 516
321 class SetTimeoutExtension : public IsolateData::SetupGlobalTask { 517 class SetTimeoutExtension : public IsolateData::SetupGlobalTask {
322 public: 518 public:
323 void Run(v8::Isolate* isolate, 519 void Run(v8::Isolate* isolate,
324 v8::Local<v8::ObjectTemplate> global) override { 520 v8::Local<v8::ObjectTemplate> global) override {
325 global->Set( 521 global->Set(
326 ToV8String(isolate, "setTimeout"), 522 ToV8String(isolate, "setTimeout"),
327 v8::FunctionTemplate::New(isolate, &SetTimeoutExtension::SetTimeout)); 523 v8::FunctionTemplate::New(isolate, &SetTimeoutExtension::SetTimeout));
328 } 524 }
329 525
330 private: 526 private:
331 static void SetTimeout(const v8::FunctionCallbackInfo<v8::Value>& args) { 527 static void SetTimeout(const v8::FunctionCallbackInfo<v8::Value>& args) {
332 if (args.Length() != 2 || !args[1]->IsNumber() || 528 if (args.Length() != 2 || !args[1]->IsNumber() ||
333 (!args[0]->IsFunction() && !args[0]->IsString()) || 529 (!args[0]->IsFunction() && !args[0]->IsString()) ||
334 args[1].As<v8::Number>()->Value() != 0.0) { 530 args[1].As<v8::Number>()->Value() != 0.0) {
335 fprintf(stderr, 531 fprintf(
336 "Internal error: only setTimeout(function, 0) is supported."); 532 stderr,
533 "Internal error: only setTimeout(function|code, 0) is supported.");
337 Exit(); 534 Exit();
338 } 535 }
339 v8::Isolate* isolate = args.GetIsolate(); 536 v8::Isolate* isolate = args.GetIsolate();
340 v8::Local<v8::Context> context = isolate->GetCurrentContext(); 537 v8::Local<v8::Context> context = isolate->GetCurrentContext();
538 IsolateData* data = IsolateData::FromContext(context);
539 int context_group_id = data->GetContextGroupId(context);
341 std::unique_ptr<TaskRunner::Task> task; 540 std::unique_ptr<TaskRunner::Task> task;
342 v8_inspector::V8Inspector* inspector =
343 InspectorClientImpl::InspectorFromContext(context);
344 if (args[0]->IsFunction()) { 541 if (args[0]->IsFunction()) {
345 task.reset(new SetTimeoutTask(isolate, 542 task.reset(new SetTimeoutTask(data, context_group_id, "setTimeout",
346 v8::Local<v8::Function>::Cast(args[0]), 543 v8::Local<v8::Function>::Cast(args[0])));
347 "setTimeout", inspector));
348 } else { 544 } else {
349 task.reset(new ExecuteStringTask( 545 task.reset(new ExecuteStringTask(
546 data, context_group_id, "setTimeout",
350 ToVector(args[0].As<v8::String>()), v8::String::Empty(isolate), 547 ToVector(args[0].As<v8::String>()), v8::String::Empty(isolate),
351 v8::Integer::New(isolate, 0), v8::Integer::New(isolate, 0), 548 v8::Integer::New(isolate, 0), v8::Integer::New(isolate, 0),
352 v8::Boolean::New(isolate, false), "setTimeout", inspector)); 549 v8::Boolean::New(isolate, false)));
353 } 550 }
354 IsolateData::FromContext(context)->task_runner()->Append(task.release()); 551 data->task_runner()->Append(task.release());
355 } 552 }
356 }; 553 };
357 554
358 bool StrictAccessCheck(v8::Local<v8::Context> accessing_context, 555 bool StrictAccessCheck(v8::Local<v8::Context> accessing_context,
359 v8::Local<v8::Object> accessed_object, 556 v8::Local<v8::Object> accessed_object,
360 v8::Local<v8::Value> data) { 557 v8::Local<v8::Value> data) {
361 CHECK(accessing_context.IsEmpty()); 558 CHECK(accessing_context.IsEmpty());
362 return accessing_context.IsEmpty(); 559 return accessing_context.IsEmpty();
363 } 560 }
364 561
365 class InspectorExtension : public IsolateData::SetupGlobalTask { 562 class InspectorExtension : public IsolateData::SetupGlobalTask {
366 public: 563 public:
367 ~InspectorExtension() override = default; 564 ~InspectorExtension() override = default;
368 void Run(v8::Isolate* isolate, 565 void Run(v8::Isolate* isolate,
369 v8::Local<v8::ObjectTemplate> global) override { 566 v8::Local<v8::ObjectTemplate> global) override {
370 v8::Local<v8::ObjectTemplate> inspector = v8::ObjectTemplate::New(isolate); 567 v8::Local<v8::ObjectTemplate> inspector = v8::ObjectTemplate::New(isolate);
371 inspector->Set( 568 inspector->Set(ToV8String(isolate, "fireContextCreated"),
372 ToV8String(isolate, "attachInspector"), 569 v8::FunctionTemplate::New(
373 v8::FunctionTemplate::New(isolate, &InspectorExtension::Attach)); 570 isolate, &InspectorExtension::FireContextCreated));
374 inspector->Set( 571 inspector->Set(ToV8String(isolate, "fireContextDestroyed"),
375 ToV8String(isolate, "detachInspector"), 572 v8::FunctionTemplate::New(
376 v8::FunctionTemplate::New(isolate, &InspectorExtension::Detach)); 573 isolate, &InspectorExtension::FireContextDestroyed));
377 inspector->Set(ToV8String(isolate, "setMaxAsyncTaskStacks"), 574 inspector->Set(ToV8String(isolate, "setMaxAsyncTaskStacks"),
378 v8::FunctionTemplate::New( 575 v8::FunctionTemplate::New(
379 isolate, &InspectorExtension::SetMaxAsyncTaskStacks)); 576 isolate, &InspectorExtension::SetMaxAsyncTaskStacks));
380 inspector->Set( 577 inspector->Set(
381 ToV8String(isolate, "dumpAsyncTaskStacksStateForTest"), 578 ToV8String(isolate, "dumpAsyncTaskStacksStateForTest"),
382 v8::FunctionTemplate::New( 579 v8::FunctionTemplate::New(
383 isolate, &InspectorExtension::DumpAsyncTaskStacksStateForTest)); 580 isolate, &InspectorExtension::DumpAsyncTaskStacksStateForTest));
384 inspector->Set( 581 inspector->Set(
385 ToV8String(isolate, "breakProgram"), 582 ToV8String(isolate, "breakProgram"),
386 v8::FunctionTemplate::New(isolate, &InspectorExtension::BreakProgram)); 583 v8::FunctionTemplate::New(isolate, &InspectorExtension::BreakProgram));
387 inspector->Set( 584 inspector->Set(
388 ToV8String(isolate, "createObjectWithStrictCheck"), 585 ToV8String(isolate, "createObjectWithStrictCheck"),
389 v8::FunctionTemplate::New( 586 v8::FunctionTemplate::New(
390 isolate, &InspectorExtension::CreateObjectWithStrictCheck)); 587 isolate, &InspectorExtension::CreateObjectWithStrictCheck));
391 inspector->Set(ToV8String(isolate, "callWithScheduledBreak"), 588 inspector->Set(ToV8String(isolate, "callWithScheduledBreak"),
392 v8::FunctionTemplate::New( 589 v8::FunctionTemplate::New(
393 isolate, &InspectorExtension::CallWithScheduledBreak)); 590 isolate, &InspectorExtension::CallWithScheduledBreak));
394 inspector->Set(ToV8String(isolate, "allowAccessorFormatting"), 591 inspector->Set(ToV8String(isolate, "allowAccessorFormatting"),
395 v8::FunctionTemplate::New( 592 v8::FunctionTemplate::New(
396 isolate, &InspectorExtension::AllowAccessorFormatting)); 593 isolate, &InspectorExtension::AllowAccessorFormatting));
397 global->Set(ToV8String(isolate, "inspector"), inspector); 594 global->Set(ToV8String(isolate, "inspector"), inspector);
398 } 595 }
399 596
400 private: 597 private:
401 static void Attach(const v8::FunctionCallbackInfo<v8::Value>& args) { 598 static void FireContextCreated(
402 v8::Isolate* isolate = args.GetIsolate(); 599 const v8::FunctionCallbackInfo<v8::Value>& args) {
403 v8::Local<v8::Context> context = isolate->GetCurrentContext(); 600 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
404 v8_inspector::V8Inspector* inspector = 601 IsolateData* data = IsolateData::FromContext(context);
405 InspectorClientImpl::InspectorFromContext(context); 602 data->inspector()->ContextCreated(context,
406 if (!inspector) { 603 data->GetContextGroupId(context));
407 fprintf(stderr, "Inspector client not found - cannot attach!");
408 Exit();
409 }
410 inspector->contextCreated(
411 v8_inspector::V8ContextInfo(context, 1, v8_inspector::StringView()));
412 } 604 }
413 605
414 static void Detach(const v8::FunctionCallbackInfo<v8::Value>& args) { 606 static void FireContextDestroyed(
415 v8::Isolate* isolate = args.GetIsolate(); 607 const v8::FunctionCallbackInfo<v8::Value>& args) {
416 v8::Local<v8::Context> context = isolate->GetCurrentContext(); 608 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
417 v8_inspector::V8Inspector* inspector = 609 IsolateData* data = IsolateData::FromContext(context);
418 InspectorClientImpl::InspectorFromContext(context); 610 data->inspector()->ContextDestroyed(context);
419 if (!inspector) {
420 fprintf(stderr, "Inspector client not found - cannot detach!");
421 Exit();
422 }
423 inspector->contextDestroyed(context);
424 } 611 }
425 612
426 static void SetMaxAsyncTaskStacks( 613 static void SetMaxAsyncTaskStacks(
427 const v8::FunctionCallbackInfo<v8::Value>& args) { 614 const v8::FunctionCallbackInfo<v8::Value>& args) {
428 if (args.Length() != 1 || !args[0]->IsInt32()) { 615 if (args.Length() != 1 || !args[0]->IsInt32()) {
429 fprintf(stderr, "Internal error: setMaxAsyncTaskStacks(max)."); 616 fprintf(stderr, "Internal error: setMaxAsyncTaskStacks(max).");
430 Exit(); 617 Exit();
431 } 618 }
432 v8_inspector::V8Inspector* inspector =
433 InspectorClientImpl::InspectorFromContext(
434 args.GetIsolate()->GetCurrentContext());
435 CHECK(inspector);
436 v8_inspector::SetMaxAsyncTaskStacksForTest( 619 v8_inspector::SetMaxAsyncTaskStacksForTest(
437 inspector, args[0].As<v8::Int32>()->Value()); 620 IsolateData::FromContext(args.GetIsolate()->GetCurrentContext())
621 ->inspector()
622 ->inspector(),
623 args[0].As<v8::Int32>()->Value());
438 } 624 }
439 625
440 static void DumpAsyncTaskStacksStateForTest( 626 static void DumpAsyncTaskStacksStateForTest(
441 const v8::FunctionCallbackInfo<v8::Value>& args) { 627 const v8::FunctionCallbackInfo<v8::Value>& args) {
442 if (args.Length() != 0) { 628 if (args.Length() != 0) {
443 fprintf(stderr, "Internal error: dumpAsyncTaskStacksStateForTest()."); 629 fprintf(stderr, "Internal error: dumpAsyncTaskStacksStateForTest().");
444 Exit(); 630 Exit();
445 } 631 }
446 v8_inspector::V8Inspector* inspector = 632 v8_inspector::DumpAsyncTaskStacksStateForTest(
447 InspectorClientImpl::InspectorFromContext( 633 IsolateData::FromContext(args.GetIsolate()->GetCurrentContext())
448 args.GetIsolate()->GetCurrentContext()); 634 ->inspector()
449 CHECK(inspector); 635 ->inspector());
450 v8_inspector::DumpAsyncTaskStacksStateForTest(inspector);
451 } 636 }
452 637
453 static void BreakProgram(const v8::FunctionCallbackInfo<v8::Value>& args) { 638 static void BreakProgram(const v8::FunctionCallbackInfo<v8::Value>& args) {
454 if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsString()) { 639 if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsString()) {
455 fprintf(stderr, "Internal error: breakProgram('reason', 'details')."); 640 fprintf(stderr, "Internal error: breakProgram('reason', 'details').");
456 Exit(); 641 Exit();
457 } 642 }
458 v8_inspector::V8InspectorSession* session = 643 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
459 InspectorClientImpl::SessionFromContext( 644 IsolateData* data = IsolateData::FromContext(context);
460 args.GetIsolate()->GetCurrentContext());
461 CHECK(session);
462
463 v8::internal::Vector<uint16_t> reason = ToVector(args[0].As<v8::String>()); 645 v8::internal::Vector<uint16_t> reason = ToVector(args[0].As<v8::String>());
464 v8_inspector::StringView reason_view(reason.start(), reason.length()); 646 v8_inspector::StringView reason_view(reason.start(), reason.length());
465 v8::internal::Vector<uint16_t> details = ToVector(args[1].As<v8::String>()); 647 v8::internal::Vector<uint16_t> details = ToVector(args[1].As<v8::String>());
466 v8_inspector::StringView details_view(details.start(), details.length()); 648 v8_inspector::StringView details_view(details.start(), details.length());
467 session->breakProgram(reason_view, details_view); 649 data->inspector()->BreakProgram(data->GetContextGroupId(context),
650 reason_view, details_view);
468 } 651 }
469 652
470 static void CreateObjectWithStrictCheck( 653 static void CreateObjectWithStrictCheck(
471 const v8::FunctionCallbackInfo<v8::Value>& args) { 654 const v8::FunctionCallbackInfo<v8::Value>& args) {
472 if (args.Length() != 0) { 655 if (args.Length() != 0) {
473 fprintf(stderr, "Internal error: createObjectWithStrictCheck()."); 656 fprintf(stderr, "Internal error: createObjectWithStrictCheck().");
474 Exit(); 657 Exit();
475 } 658 }
476 v8::Local<v8::ObjectTemplate> templ = 659 v8::Local<v8::ObjectTemplate> templ =
477 v8::ObjectTemplate::New(args.GetIsolate()); 660 v8::ObjectTemplate::New(args.GetIsolate());
478 templ->SetAccessCheckCallback(&StrictAccessCheck); 661 templ->SetAccessCheckCallback(&StrictAccessCheck);
479 args.GetReturnValue().Set( 662 args.GetReturnValue().Set(
480 templ->NewInstance(args.GetIsolate()->GetCurrentContext()) 663 templ->NewInstance(args.GetIsolate()->GetCurrentContext())
481 .ToLocalChecked()); 664 .ToLocalChecked());
482 } 665 }
483 666
484 static void CallWithScheduledBreak( 667 static void CallWithScheduledBreak(
485 const v8::FunctionCallbackInfo<v8::Value>& args) { 668 const v8::FunctionCallbackInfo<v8::Value>& args) {
486 if (args.Length() != 3 || !args[0]->IsFunction() || !args[1]->IsString() || 669 if (args.Length() != 3 || !args[0]->IsFunction() || !args[1]->IsString() ||
487 !args[2]->IsString()) { 670 !args[2]->IsString()) {
488 fprintf(stderr, "Internal error: breakProgram('reason', 'details')."); 671 fprintf(stderr,
672 "Internal error: callWithScheduledBreak('reason', 'details').");
489 Exit(); 673 Exit();
490 } 674 }
491 v8_inspector::V8InspectorSession* session =
492 InspectorClientImpl::SessionFromContext(
493 args.GetIsolate()->GetCurrentContext());
494 CHECK(session);
495
496 v8::internal::Vector<uint16_t> reason = ToVector(args[1].As<v8::String>()); 675 v8::internal::Vector<uint16_t> reason = ToVector(args[1].As<v8::String>());
497 v8_inspector::StringView reason_view(reason.start(), reason.length()); 676 v8_inspector::StringView reason_view(reason.start(), reason.length());
498 v8::internal::Vector<uint16_t> details = ToVector(args[2].As<v8::String>()); 677 v8::internal::Vector<uint16_t> details = ToVector(args[2].As<v8::String>());
499 v8_inspector::StringView details_view(details.start(), details.length()); 678 v8_inspector::StringView details_view(details.start(), details.length());
500 session->schedulePauseOnNextStatement(reason_view, details_view);
501 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext(); 679 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
680 IsolateData* data = IsolateData::FromContext(context);
681 int context_group_id = data->GetContextGroupId(context);
682 data->inspector()->SchedulePauseOnNextStatement(context_group_id,
683 reason_view, details_view);
502 v8::MaybeLocal<v8::Value> result; 684 v8::MaybeLocal<v8::Value> result;
503 result = args[0].As<v8::Function>()->Call(context, context->Global(), 0, 685 result = args[0].As<v8::Function>()->Call(context, context->Global(), 0,
504 nullptr); 686 nullptr);
505 session->cancelPauseOnNextStatement(); 687 data->inspector()->CancelPauseOnNextStatement(context_group_id);
506 } 688 }
507 689
508 static void AllowAccessorFormatting( 690 static void AllowAccessorFormatting(
509 const v8::FunctionCallbackInfo<v8::Value>& args) { 691 const v8::FunctionCallbackInfo<v8::Value>& args) {
510 if (args.Length() != 1 || !args[0]->IsObject()) { 692 if (args.Length() != 1 || !args[0]->IsObject()) {
511 fprintf(stderr, "Internal error: allowAccessorFormatting('object')."); 693 fprintf(stderr, "Internal error: allowAccessorFormatting('object').");
512 Exit(); 694 Exit();
513 } 695 }
514 v8::Local<v8::Object> object = args[0].As<v8::Object>(); 696 v8::Local<v8::Object> object = args[0].As<v8::Object>();
515 v8::Isolate* isolate = args.GetIsolate(); 697 v8::Isolate* isolate = args.GetIsolate();
516 v8::Local<v8::Private> shouldFormatAccessorsPrivate = v8::Private::ForApi( 698 v8::Local<v8::Private> shouldFormatAccessorsPrivate = v8::Private::ForApi(
517 isolate, v8::String::NewFromUtf8(isolate, "allowAccessorFormatting", 699 isolate, v8::String::NewFromUtf8(isolate, "allowAccessorFormatting",
518 v8::NewStringType::kNormal) 700 v8::NewStringType::kNormal)
519 .ToLocalChecked()); 701 .ToLocalChecked());
520 object 702 object
521 ->SetPrivate(isolate->GetCurrentContext(), shouldFormatAccessorsPrivate, 703 ->SetPrivate(isolate->GetCurrentContext(), shouldFormatAccessorsPrivate,
522 v8::Null(isolate)) 704 v8::Null(isolate))
523 .ToChecked(); 705 .ToChecked();
524 } 706 }
525 }; 707 };
526 708
527 void UtilsExtension::CreateContextGroup(
528 const v8::FunctionCallbackInfo<v8::Value>& args) {
529 if (args.Length() != 0) {
530 fprintf(stderr, "Internal error: createContextGroup().");
531 Exit();
532 }
533 v8::base::Semaphore ready_semaphore(0);
534 int context_group_id = 0;
535 IsolateData::SetupGlobalTasks setup_global;
536 setup_global.emplace_back(new SetTimeoutExtension());
537 setup_global.emplace_back(new InspectorExtension());
538 inspector_client_->scheduleCreateContextGroup(
539 std::move(setup_global), &ready_semaphore, &context_group_id);
540 ready_semaphore.Wait();
541 args.GetReturnValue().Set(
542 v8::Int32::New(args.GetIsolate(), context_group_id));
543 }
544
545 v8::Local<v8::String> ToString(v8::Isolate* isolate, 709 v8::Local<v8::String> ToString(v8::Isolate* isolate,
546 const v8_inspector::StringView& string) { 710 const v8_inspector::StringView& string) {
547 if (string.is8Bit()) 711 if (string.is8Bit())
548 return v8::String::NewFromOneByte(isolate, string.characters8(), 712 return v8::String::NewFromOneByte(isolate, string.characters8(),
549 v8::NewStringType::kNormal, 713 v8::NewStringType::kNormal,
550 static_cast<int>(string.length())) 714 static_cast<int>(string.length()))
551 .ToLocalChecked(); 715 .ToLocalChecked();
552 else 716 else
553 return v8::String::NewFromTwoByte(isolate, string.characters16(), 717 return v8::String::NewFromTwoByte(isolate, string.characters16(),
554 v8::NewStringType::kNormal, 718 v8::NewStringType::kNormal,
555 static_cast<int>(string.length())) 719 static_cast<int>(string.length()))
556 .ToLocalChecked(); 720 .ToLocalChecked();
557 } 721 }
558 722
559 class FrontendChannelImpl : public InspectorClientImpl::FrontendChannel { 723 class FrontendChannelImpl : public InspectorClientImpl::FrontendChannel {
560 public: 724 public:
561 explicit FrontendChannelImpl(TaskRunner* frontend_task_runner) 725 FrontendChannelImpl(TaskRunner* frontend_task_runner, int context_group_id)
562 : frontend_task_runner_(frontend_task_runner) {} 726 : frontend_task_runner_(frontend_task_runner),
727 context_group_id_(context_group_id) {}
563 virtual ~FrontendChannelImpl() {} 728 virtual ~FrontendChannelImpl() {}
564 729
565 void SendMessageToFrontend(const v8_inspector::StringView& message) final { 730 void SendMessageToFrontend(int session_id,
731 const v8_inspector::StringView& message) final {
566 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 732 v8::Isolate* isolate = v8::Isolate::GetCurrent();
567 v8::HandleScope scope(v8::Isolate::GetCurrent()); 733 v8::HandleScope scope(v8::Isolate::GetCurrent());
568 734
569 v8::Local<v8::String> prefix = 735 v8::Local<v8::String> prefix =
570 v8::String::NewFromUtf8(isolate, "InspectorTest._dispatchMessage(", 736 v8::String::NewFromUtf8(isolate, "InspectorTest._dispatchMessage(",
571 v8::NewStringType::kInternalized) 737 v8::NewStringType::kInternalized)
572 .ToLocalChecked(); 738 .ToLocalChecked();
573 v8::Local<v8::String> message_string = ToString(isolate, message); 739 v8::Local<v8::String> message_string = ToString(isolate, message);
740 v8::internal::Vector<char> session = v8::internal::Vector<char>::New(50);
741 v8::Local<v8::String> session_string =
742 ToV8String(isolate, v8::internal::IntToCString(session_id, session));
743 v8::Local<v8::String> comma =
744 v8::String::NewFromUtf8(isolate, ",", v8::NewStringType::kInternalized)
745 .ToLocalChecked();
574 v8::Local<v8::String> suffix = 746 v8::Local<v8::String> suffix =
575 v8::String::NewFromUtf8(isolate, ")", v8::NewStringType::kInternalized) 747 v8::String::NewFromUtf8(isolate, ")", v8::NewStringType::kInternalized)
576 .ToLocalChecked(); 748 .ToLocalChecked();
577 749
578 v8::Local<v8::String> result = v8::String::Concat(prefix, message_string); 750 v8::Local<v8::String> result = v8::String::Concat(prefix, session_string);
751 result = v8::String::Concat(result, comma);
752 result = v8::String::Concat(result, message_string);
579 result = v8::String::Concat(result, suffix); 753 result = v8::String::Concat(result, suffix);
580 754
581 frontend_task_runner_->Append(new ExecuteStringTask( 755 frontend_task_runner_->Append(new ExecuteStringTask(
582 ToVector(result), v8::String::Empty(isolate), 756 nullptr, context_group_id_, nullptr, ToVector(result),
583 v8::Integer::New(isolate, 0), v8::Integer::New(isolate, 0), 757 v8::String::Empty(isolate), v8::Integer::New(isolate, 0),
584 v8::Boolean::New(isolate, false), nullptr, nullptr)); 758 v8::Integer::New(isolate, 0), v8::Boolean::New(isolate, false)));
585 } 759 }
586 760
587 private: 761 private:
588 TaskRunner* frontend_task_runner_; 762 TaskRunner* frontend_task_runner_;
763 int context_group_id_;
589 }; 764 };
590 765
591 } // namespace 766 } // namespace
592 767
593 int main(int argc, char* argv[]) { 768 int main(int argc, char* argv[]) {
594 v8::V8::InitializeICUDefaultLocation(argv[0]); 769 v8::V8::InitializeICUDefaultLocation(argv[0]);
595 v8::Platform* platform = v8::platform::CreateDefaultPlatform(); 770 v8::Platform* platform = v8::platform::CreateDefaultPlatform();
596 v8::V8::InitializePlatform(platform); 771 v8::V8::InitializePlatform(platform);
597 v8::V8::SetFlagsFromCommandLine(&argc, argv, true); 772 v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
598 v8::V8::InitializeExternalStartupData(argv[0]); 773 v8::V8::InitializeExternalStartupData(argv[0]);
599 v8::V8::Initialize(); 774 v8::V8::Initialize();
600 775
601 v8::base::Semaphore ready_semaphore(0); 776 v8::base::Semaphore ready_semaphore(0);
602 777
603 v8::StartupData startup_data = {nullptr, 0}; 778 v8::StartupData startup_data = {nullptr, 0};
604 for (int i = 1; i < argc; ++i) { 779 for (int i = 1; i < argc; ++i) {
605 if (strcmp(argv[i], "--embed") == 0) { 780 if (strcmp(argv[i], "--embed") == 0) {
606 argv[i++] = nullptr; 781 argv[i++] = nullptr;
607 printf("Embedding script '%s'\n", argv[i]); 782 printf("Embedding script '%s'\n", argv[i]);
608 startup_data = v8::V8::CreateSnapshotDataBlob(argv[i]); 783 startup_data = v8::V8::CreateSnapshotDataBlob(argv[i]);
609 argv[i] = nullptr; 784 argv[i] = nullptr;
610 } 785 }
611 } 786 }
612 787
788 IsolateData::SetupGlobalTasks frontend_extensions;
789 frontend_extensions.emplace_back(new UtilsExtension());
790 TaskRunner frontend_runner(std::move(frontend_extensions), true,
791 &ready_semaphore, nullptr, nullptr);
792 ready_semaphore.Wait();
793
794 int frontend_context_group_id = 0;
795 frontend_runner.Append(
796 new CreateContextGroupTask(&ready_semaphore, &frontend_context_group_id));
797 ready_semaphore.Wait();
798
613 IsolateData::SetupGlobalTasks backend_extensions; 799 IsolateData::SetupGlobalTasks backend_extensions;
614 backend_extensions.emplace_back(new SetTimeoutExtension()); 800 backend_extensions.emplace_back(new SetTimeoutExtension());
615 backend_extensions.emplace_back(new InspectorExtension()); 801 backend_extensions.emplace_back(new InspectorExtension());
616 TaskRunner backend_runner(std::move(backend_extensions), false, 802 FrontendChannelImpl frontend_channel(&frontend_runner,
617 &ready_semaphore, 803 frontend_context_group_id);
618 startup_data.data ? &startup_data : nullptr); 804 TaskRunner backend_runner(
805 std::move(backend_extensions), false, &ready_semaphore,
806 startup_data.data ? &startup_data : nullptr, &frontend_channel);
619 ready_semaphore.Wait(); 807 ready_semaphore.Wait();
620 SendMessageToBackendExtension::set_backend_task_runner(&backend_runner);
621 UtilsExtension::set_backend_task_runner(&backend_runner); 808 UtilsExtension::set_backend_task_runner(&backend_runner);
622 809
623 IsolateData::SetupGlobalTasks frontend_extensions;
624 frontend_extensions.emplace_back(new UtilsExtension());
625 frontend_extensions.emplace_back(new SendMessageToBackendExtension());
626 TaskRunner frontend_runner(std::move(frontend_extensions), true,
627 &ready_semaphore, nullptr);
628 ready_semaphore.Wait();
629
630 FrontendChannelImpl frontend_channel(&frontend_runner);
631 InspectorClientImpl inspector_client(&backend_runner, &frontend_channel,
632 &ready_semaphore);
633 ready_semaphore.Wait();
634 UtilsExtension::set_inspector_client(&inspector_client);
635
636 task_runners.push_back(&frontend_runner); 810 task_runners.push_back(&frontend_runner);
637 task_runners.push_back(&backend_runner); 811 task_runners.push_back(&backend_runner);
638 812
639 for (int i = 1; i < argc; ++i) { 813 for (int i = 1; i < argc; ++i) {
640 // Ignore unknown flags. 814 // Ignore unknown flags.
641 if (argv[i] == nullptr || argv[i][0] == '-') continue; 815 if (argv[i] == nullptr || argv[i][0] == '-') continue;
642 816
643 bool exists = false; 817 bool exists = false;
644 v8::internal::Vector<const char> chars = 818 v8::internal::Vector<const char> chars =
645 v8::internal::ReadFile(argv[i], &exists, true); 819 v8::internal::ReadFile(argv[i], &exists, true);
646 if (!exists) { 820 if (!exists) {
647 fprintf(stderr, "Internal error: script file doesn't exists: %s\n", 821 fprintf(stderr, "Internal error: script file doesn't exists: %s\n",
648 argv[i]); 822 argv[i]);
649 Exit(); 823 Exit();
650 } 824 }
651 frontend_runner.Append(new ExecuteStringTask(chars)); 825 frontend_runner.Append(
826 new ExecuteStringTask(chars, frontend_context_group_id));
652 } 827 }
653 828
654 frontend_runner.Join(); 829 frontend_runner.Join();
655 backend_runner.Join(); 830 backend_runner.Join();
656 831
657 delete startup_data.data; 832 delete startup_data.data;
658 return 0; 833 return 0;
659 } 834 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698