| 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 |