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 |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |