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