Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #if !defined(_WIN32) && !defined(_WIN64) | 5 #if !defined(_WIN32) && !defined(_WIN64) |
| 6 #include <unistd.h> // NOLINT | 6 #include <unistd.h> // NOLINT |
| 7 #endif // !defined(_WIN32) && !defined(_WIN64) | 7 #endif // !defined(_WIN32) && !defined(_WIN64) |
| 8 | 8 |
| 9 #include <locale.h> | 9 #include <locale.h> |
| 10 | 10 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 44 v8::internal::Vector<uint16_t>::New(str->Length()); | 44 v8::internal::Vector<uint16_t>::New(str->Length()); |
| 45 str->Write(buffer.start(), 0, str->Length()); | 45 str->Write(buffer.start(), 0, str->Length()); |
| 46 return buffer; | 46 return buffer; |
| 47 } | 47 } |
| 48 | 48 |
| 49 v8::Local<v8::String> ToV8String(v8::Isolate* isolate, const char* str) { | 49 v8::Local<v8::String> ToV8String(v8::Isolate* isolate, const char* str) { |
| 50 return v8::String::NewFromUtf8(isolate, str, v8::NewStringType::kNormal) | 50 return v8::String::NewFromUtf8(isolate, str, v8::NewStringType::kNormal) |
| 51 .ToLocalChecked(); | 51 .ToLocalChecked(); |
| 52 } | 52 } |
| 53 | 53 |
| 54 class UtilsExtension : public TaskRunner::Task { | 54 class SetTimeoutTask : public AsyncTask { |
|
dgozman
2017/04/20 23:16:38
Why move the code? Put it back for small delta.
kozy
2017/04/20 23:38:19
Done.
| |
| 55 public: | |
| 56 SetTimeoutTask(v8::Isolate* isolate, v8::Local<v8::Function> function, | |
| 57 const char* task_name, v8_inspector::V8Inspector* inspector) | |
| 58 : AsyncTask(task_name, inspector), function_(isolate, function) {} | |
| 59 virtual ~SetTimeoutTask() {} | |
| 60 | |
| 61 bool is_inspector_task() final { return false; } | |
| 62 | |
| 63 void AsyncRun(v8::Isolate* isolate, | |
| 64 const v8::Global<v8::Context>& global_context) override { | |
| 65 v8::MicrotasksScope microtasks_scope(isolate, | |
| 66 v8::MicrotasksScope::kRunMicrotasks); | |
| 67 v8::HandleScope handle_scope(isolate); | |
| 68 v8::Local<v8::Context> context = global_context.Get(isolate); | |
| 69 v8::Context::Scope context_scope(context); | |
| 70 | |
| 71 v8::Local<v8::Function> function = function_.Get(isolate); | |
| 72 v8::MaybeLocal<v8::Value> result; | |
| 73 result = function->Call(context, context->Global(), 0, nullptr); | |
| 74 } | |
| 75 | |
| 76 private: | |
| 77 v8::Global<v8::Function> function_; | |
| 78 }; | |
| 79 | |
| 80 class SetTimeoutExtension : public TaskRunner::SetupGlobalTask { | |
| 81 public: | |
| 82 void Run(v8::Isolate* isolate, | |
| 83 v8::Local<v8::ObjectTemplate> global) override { | |
| 84 global->Set( | |
| 85 ToV8String(isolate, "setTimeout"), | |
| 86 v8::FunctionTemplate::New(isolate, &SetTimeoutExtension::SetTimeout)); | |
| 87 } | |
| 88 | |
| 89 private: | |
| 90 static void SetTimeout(const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 91 if (args.Length() != 2 || !args[1]->IsNumber() || | |
| 92 (!args[0]->IsFunction() && !args[0]->IsString()) || | |
| 93 args[1].As<v8::Number>()->Value() != 0.0) { | |
| 94 fprintf(stderr, | |
| 95 "Internal error: only setTimeout(function, 0) is supported."); | |
| 96 Exit(); | |
| 97 } | |
| 98 v8::Isolate* isolate = args.GetIsolate(); | |
| 99 v8::Local<v8::Context> context = isolate->GetCurrentContext(); | |
| 100 std::unique_ptr<TaskRunner::Task> task; | |
| 101 v8_inspector::V8Inspector* inspector = | |
| 102 InspectorClientImpl::InspectorFromContext(context); | |
| 103 if (args[0]->IsFunction()) { | |
| 104 task.reset(new SetTimeoutTask(isolate, | |
| 105 v8::Local<v8::Function>::Cast(args[0]), | |
| 106 "setTimeout", inspector)); | |
| 107 } else { | |
| 108 task.reset(new ExecuteStringTask( | |
| 109 ToVector(args[0].As<v8::String>()), v8::String::Empty(isolate), | |
| 110 v8::Integer::New(isolate, 0), v8::Integer::New(isolate, 0), | |
| 111 v8::Boolean::New(isolate, false), "setTimeout", inspector)); | |
| 112 } | |
| 113 TaskRunner::FromContext(context)->Append(task.release()); | |
| 114 } | |
| 115 }; | |
| 116 | |
| 117 bool StrictAccessCheck(v8::Local<v8::Context> accessing_context, | |
| 118 v8::Local<v8::Object> accessed_object, | |
| 119 v8::Local<v8::Value> data) { | |
| 120 CHECK(accessing_context.IsEmpty()); | |
| 121 return accessing_context.IsEmpty(); | |
| 122 } | |
| 123 | |
| 124 class InspectorExtension : public TaskRunner::SetupGlobalTask { | |
| 125 public: | |
| 126 ~InspectorExtension() override = default; | |
| 127 void Run(v8::Isolate* isolate, | |
| 128 v8::Local<v8::ObjectTemplate> global) override { | |
| 129 v8::Local<v8::ObjectTemplate> inspector = v8::ObjectTemplate::New(isolate); | |
| 130 inspector->Set( | |
| 131 ToV8String(isolate, "attachInspector"), | |
| 132 v8::FunctionTemplate::New(isolate, &InspectorExtension::Attach)); | |
| 133 inspector->Set( | |
| 134 ToV8String(isolate, "detachInspector"), | |
| 135 v8::FunctionTemplate::New(isolate, &InspectorExtension::Detach)); | |
| 136 inspector->Set(ToV8String(isolate, "setMaxAsyncTaskStacks"), | |
| 137 v8::FunctionTemplate::New( | |
| 138 isolate, &InspectorExtension::SetMaxAsyncTaskStacks)); | |
| 139 inspector->Set( | |
| 140 ToV8String(isolate, "dumpAsyncTaskStacksStateForTest"), | |
| 141 v8::FunctionTemplate::New( | |
| 142 isolate, &InspectorExtension::DumpAsyncTaskStacksStateForTest)); | |
| 143 inspector->Set( | |
| 144 ToV8String(isolate, "breakProgram"), | |
| 145 v8::FunctionTemplate::New(isolate, &InspectorExtension::BreakProgram)); | |
| 146 inspector->Set( | |
| 147 ToV8String(isolate, "createObjectWithStrictCheck"), | |
| 148 v8::FunctionTemplate::New( | |
| 149 isolate, &InspectorExtension::CreateObjectWithStrictCheck)); | |
| 150 inspector->Set(ToV8String(isolate, "callWithScheduledBreak"), | |
| 151 v8::FunctionTemplate::New( | |
| 152 isolate, &InspectorExtension::CallWithScheduledBreak)); | |
| 153 inspector->Set(ToV8String(isolate, "allowAccessorFormatting"), | |
| 154 v8::FunctionTemplate::New( | |
| 155 isolate, &InspectorExtension::AllowAccessorFormatting)); | |
| 156 global->Set(ToV8String(isolate, "inspector"), inspector); | |
| 157 } | |
| 158 | |
| 159 private: | |
| 160 static void Attach(const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 161 v8::Isolate* isolate = args.GetIsolate(); | |
| 162 v8::Local<v8::Context> context = isolate->GetCurrentContext(); | |
| 163 v8_inspector::V8Inspector* inspector = | |
| 164 InspectorClientImpl::InspectorFromContext(context); | |
| 165 if (!inspector) { | |
| 166 fprintf(stderr, "Inspector client not found - cannot attach!"); | |
| 167 Exit(); | |
| 168 } | |
| 169 inspector->contextCreated( | |
| 170 v8_inspector::V8ContextInfo(context, 1, v8_inspector::StringView())); | |
| 171 } | |
| 172 | |
| 173 static void Detach(const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 174 v8::Isolate* isolate = args.GetIsolate(); | |
| 175 v8::Local<v8::Context> context = isolate->GetCurrentContext(); | |
| 176 v8_inspector::V8Inspector* inspector = | |
| 177 InspectorClientImpl::InspectorFromContext(context); | |
| 178 if (!inspector) { | |
| 179 fprintf(stderr, "Inspector client not found - cannot detach!"); | |
| 180 Exit(); | |
| 181 } | |
| 182 inspector->contextDestroyed(context); | |
| 183 } | |
| 184 | |
| 185 static void SetMaxAsyncTaskStacks( | |
| 186 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 187 if (args.Length() != 1 || !args[0]->IsInt32()) { | |
| 188 fprintf(stderr, "Internal error: setMaxAsyncTaskStacks(max)."); | |
| 189 Exit(); | |
| 190 } | |
| 191 v8_inspector::V8Inspector* inspector = | |
| 192 InspectorClientImpl::InspectorFromContext( | |
| 193 args.GetIsolate()->GetCurrentContext()); | |
| 194 CHECK(inspector); | |
| 195 v8_inspector::SetMaxAsyncTaskStacksForTest( | |
| 196 inspector, args[0].As<v8::Int32>()->Value()); | |
| 197 } | |
| 198 | |
| 199 static void DumpAsyncTaskStacksStateForTest( | |
| 200 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 201 if (args.Length() != 0) { | |
| 202 fprintf(stderr, "Internal error: dumpAsyncTaskStacksStateForTest()."); | |
| 203 Exit(); | |
| 204 } | |
| 205 v8_inspector::V8Inspector* inspector = | |
| 206 InspectorClientImpl::InspectorFromContext( | |
| 207 args.GetIsolate()->GetCurrentContext()); | |
| 208 CHECK(inspector); | |
| 209 v8_inspector::DumpAsyncTaskStacksStateForTest(inspector); | |
| 210 } | |
| 211 | |
| 212 static void BreakProgram(const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 213 if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsString()) { | |
| 214 fprintf(stderr, "Internal error: breakProgram('reason', 'details')."); | |
| 215 Exit(); | |
| 216 } | |
| 217 v8_inspector::V8InspectorSession* session = | |
| 218 InspectorClientImpl::SessionFromContext( | |
| 219 args.GetIsolate()->GetCurrentContext()); | |
| 220 CHECK(session); | |
| 221 | |
| 222 v8::internal::Vector<uint16_t> reason = ToVector(args[0].As<v8::String>()); | |
| 223 v8_inspector::StringView reason_view(reason.start(), reason.length()); | |
| 224 v8::internal::Vector<uint16_t> details = ToVector(args[1].As<v8::String>()); | |
| 225 v8_inspector::StringView details_view(details.start(), details.length()); | |
| 226 session->breakProgram(reason_view, details_view); | |
| 227 } | |
| 228 | |
| 229 static void CreateObjectWithStrictCheck( | |
| 230 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 231 if (args.Length() != 0) { | |
| 232 fprintf(stderr, "Internal error: createObjectWithStrictCheck()."); | |
| 233 Exit(); | |
| 234 } | |
| 235 v8::Local<v8::ObjectTemplate> templ = | |
| 236 v8::ObjectTemplate::New(args.GetIsolate()); | |
| 237 templ->SetAccessCheckCallback(&StrictAccessCheck); | |
| 238 args.GetReturnValue().Set( | |
| 239 templ->NewInstance(args.GetIsolate()->GetCurrentContext()) | |
| 240 .ToLocalChecked()); | |
| 241 } | |
| 242 | |
| 243 static void CallWithScheduledBreak( | |
| 244 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 245 if (args.Length() != 3 || !args[0]->IsFunction() || !args[1]->IsString() || | |
| 246 !args[2]->IsString()) { | |
| 247 fprintf(stderr, "Internal error: breakProgram('reason', 'details')."); | |
| 248 Exit(); | |
| 249 } | |
| 250 v8_inspector::V8InspectorSession* session = | |
| 251 InspectorClientImpl::SessionFromContext( | |
| 252 args.GetIsolate()->GetCurrentContext()); | |
| 253 CHECK(session); | |
| 254 | |
| 255 v8::internal::Vector<uint16_t> reason = ToVector(args[1].As<v8::String>()); | |
| 256 v8_inspector::StringView reason_view(reason.start(), reason.length()); | |
| 257 v8::internal::Vector<uint16_t> details = ToVector(args[2].As<v8::String>()); | |
| 258 v8_inspector::StringView details_view(details.start(), details.length()); | |
| 259 session->schedulePauseOnNextStatement(reason_view, details_view); | |
| 260 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext(); | |
| 261 v8::MaybeLocal<v8::Value> result; | |
| 262 result = args[0].As<v8::Function>()->Call(context, context->Global(), 0, | |
| 263 nullptr); | |
| 264 session->cancelPauseOnNextStatement(); | |
| 265 } | |
| 266 | |
| 267 static void AllowAccessorFormatting( | |
| 268 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 269 if (args.Length() != 1 || !args[0]->IsObject()) { | |
| 270 fprintf(stderr, "Internal error: allowAccessorFormatting('object')."); | |
| 271 Exit(); | |
| 272 } | |
| 273 v8::Local<v8::Object> object = args[0].As<v8::Object>(); | |
| 274 v8::Isolate* isolate = args.GetIsolate(); | |
| 275 v8::Local<v8::Private> shouldFormatAccessorsPrivate = v8::Private::ForApi( | |
| 276 isolate, v8::String::NewFromUtf8(isolate, "allowAccessorFormatting", | |
| 277 v8::NewStringType::kNormal) | |
| 278 .ToLocalChecked()); | |
| 279 object | |
| 280 ->SetPrivate(isolate->GetCurrentContext(), shouldFormatAccessorsPrivate, | |
| 281 v8::Null(isolate)) | |
| 282 .ToChecked(); | |
| 283 } | |
| 284 }; | |
| 285 | |
| 286 class UtilsExtension : public TaskRunner::SetupGlobalTask { | |
| 55 public: | 287 public: |
| 56 ~UtilsExtension() override = default; | 288 ~UtilsExtension() override = default; |
| 57 bool is_inspector_task() override { return true; } | |
| 58 void Run(v8::Isolate* isolate, | 289 void Run(v8::Isolate* isolate, |
| 59 const v8::Global<v8::Context>& context) override { | 290 v8::Local<v8::ObjectTemplate> global) override { |
| 60 v8::HandleScope handle_scope(isolate); | |
| 61 v8::Local<v8::Context> local_context = context.Get(isolate); | |
| 62 v8::Context::Scope context_scope(local_context); | |
| 63 v8::Local<v8::ObjectTemplate> utils = v8::ObjectTemplate::New(isolate); | 291 v8::Local<v8::ObjectTemplate> utils = v8::ObjectTemplate::New(isolate); |
| 64 utils->Set(ToV8String(isolate, "print"), | 292 utils->Set(ToV8String(isolate, "print"), |
| 65 v8::FunctionTemplate::New(isolate, &UtilsExtension::Print)); | 293 v8::FunctionTemplate::New(isolate, &UtilsExtension::Print)); |
| 66 utils->Set(ToV8String(isolate, "quit"), | 294 utils->Set(ToV8String(isolate, "quit"), |
| 67 v8::FunctionTemplate::New(isolate, &UtilsExtension::Quit)); | 295 v8::FunctionTemplate::New(isolate, &UtilsExtension::Quit)); |
| 68 utils->Set(ToV8String(isolate, "setlocale"), | 296 utils->Set(ToV8String(isolate, "setlocale"), |
| 69 v8::FunctionTemplate::New(isolate, &UtilsExtension::Setlocale)); | 297 v8::FunctionTemplate::New(isolate, &UtilsExtension::Setlocale)); |
| 70 utils->Set(ToV8String(isolate, "read"), | 298 utils->Set(ToV8String(isolate, "read"), |
| 71 v8::FunctionTemplate::New(isolate, &UtilsExtension::Read)); | 299 v8::FunctionTemplate::New(isolate, &UtilsExtension::Read)); |
| 72 utils->Set(ToV8String(isolate, "load"), | 300 utils->Set(ToV8String(isolate, "load"), |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 87 v8::FunctionTemplate::New( | 315 v8::FunctionTemplate::New( |
| 88 isolate, &UtilsExtension::CancelPauseOnNextStatement)); | 316 isolate, &UtilsExtension::CancelPauseOnNextStatement)); |
| 89 utils->Set(ToV8String(isolate, "reconnect"), | 317 utils->Set(ToV8String(isolate, "reconnect"), |
| 90 v8::FunctionTemplate::New(isolate, &UtilsExtension::Reconnect)); | 318 v8::FunctionTemplate::New(isolate, &UtilsExtension::Reconnect)); |
| 91 utils->Set(ToV8String(isolate, "setLogConsoleApiMessageCalls"), | 319 utils->Set(ToV8String(isolate, "setLogConsoleApiMessageCalls"), |
| 92 v8::FunctionTemplate::New( | 320 v8::FunctionTemplate::New( |
| 93 isolate, &UtilsExtension::SetLogConsoleApiMessageCalls)); | 321 isolate, &UtilsExtension::SetLogConsoleApiMessageCalls)); |
| 94 utils->Set(ToV8String(isolate, "createContextGroup"), | 322 utils->Set(ToV8String(isolate, "createContextGroup"), |
| 95 v8::FunctionTemplate::New(isolate, | 323 v8::FunctionTemplate::New(isolate, |
| 96 &UtilsExtension::CreateContextGroup)); | 324 &UtilsExtension::CreateContextGroup)); |
| 97 local_context->Global() | 325 global->Set(ToV8String(isolate, "utils"), utils); |
| 98 ->Set(local_context, ToV8String(isolate, "utils"), | |
| 99 utils->NewInstance(local_context).ToLocalChecked()) | |
| 100 .ToChecked(); | |
| 101 } | 326 } |
| 102 | 327 |
| 103 static void set_backend_task_runner(TaskRunner* runner) { | 328 static void set_backend_task_runner(TaskRunner* runner) { |
| 104 backend_runner_ = runner; | 329 backend_runner_ = runner; |
| 105 } | 330 } |
| 106 | 331 |
| 107 static void set_inspector_client(InspectorClientImpl* client) { | 332 static void set_inspector_client(InspectorClientImpl* client) { |
| 108 inspector_client_ = client; | 333 inspector_client_ = client; |
| 109 } | 334 } |
| 110 | 335 |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 280 inspector_client_->setLogConsoleApiMessageCalls( | 505 inspector_client_->setLogConsoleApiMessageCalls( |
| 281 args[0].As<v8::Boolean>()->Value()); | 506 args[0].As<v8::Boolean>()->Value()); |
| 282 } | 507 } |
| 283 | 508 |
| 284 static void CreateContextGroup( | 509 static void CreateContextGroup( |
| 285 const v8::FunctionCallbackInfo<v8::Value>& args) { | 510 const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 286 if (args.Length() != 0) { | 511 if (args.Length() != 0) { |
| 287 fprintf(stderr, "Internal error: createContextGroup()."); | 512 fprintf(stderr, "Internal error: createContextGroup()."); |
| 288 Exit(); | 513 Exit(); |
| 289 } | 514 } |
| 290 const char* backend_extensions[] = {"v8_inspector/setTimeout", | |
| 291 "v8_inspector/inspector"}; | |
| 292 v8::ExtensionConfiguration backend_configuration( | |
| 293 arraysize(backend_extensions), backend_extensions); | |
| 294 v8::base::Semaphore ready_semaphore(0); | 515 v8::base::Semaphore ready_semaphore(0); |
| 295 int context_group_id = 0; | 516 int context_group_id = 0; |
| 517 TaskRunner::SetupGlobalTasks setup_global; | |
| 518 setup_global.emplace_back(new SetTimeoutExtension()); | |
| 519 setup_global.emplace_back(new InspectorExtension()); | |
| 296 inspector_client_->scheduleCreateContextGroup( | 520 inspector_client_->scheduleCreateContextGroup( |
| 297 &backend_configuration, &ready_semaphore, &context_group_id); | 521 std::move(setup_global), &ready_semaphore, &context_group_id); |
| 298 ready_semaphore.Wait(); | 522 ready_semaphore.Wait(); |
| 299 args.GetReturnValue().Set( | 523 args.GetReturnValue().Set( |
| 300 v8::Int32::New(args.GetIsolate(), context_group_id)); | 524 v8::Int32::New(args.GetIsolate(), context_group_id)); |
| 301 } | 525 } |
| 302 }; | 526 }; |
| 303 | 527 |
| 304 TaskRunner* UtilsExtension::backend_runner_ = nullptr; | 528 TaskRunner* UtilsExtension::backend_runner_ = nullptr; |
| 305 InspectorClientImpl* UtilsExtension::inspector_client_ = nullptr; | 529 InspectorClientImpl* UtilsExtension::inspector_client_ = nullptr; |
| 306 | 530 |
| 307 class SetTimeoutTask : public AsyncTask { | |
| 308 public: | |
| 309 SetTimeoutTask(v8::Isolate* isolate, v8::Local<v8::Function> function, | |
| 310 const char* task_name, v8_inspector::V8Inspector* inspector) | |
| 311 : AsyncTask(task_name, inspector), function_(isolate, function) {} | |
| 312 virtual ~SetTimeoutTask() {} | |
| 313 | |
| 314 bool is_inspector_task() final { return false; } | |
| 315 | |
| 316 void AsyncRun(v8::Isolate* isolate, | |
| 317 const v8::Global<v8::Context>& global_context) override { | |
| 318 v8::MicrotasksScope microtasks_scope(isolate, | |
| 319 v8::MicrotasksScope::kRunMicrotasks); | |
| 320 v8::HandleScope handle_scope(isolate); | |
| 321 v8::Local<v8::Context> context = global_context.Get(isolate); | |
| 322 v8::Context::Scope context_scope(context); | |
| 323 | |
| 324 v8::Local<v8::Function> function = function_.Get(isolate); | |
| 325 v8::MaybeLocal<v8::Value> result; | |
| 326 result = function->Call(context, context->Global(), 0, nullptr); | |
| 327 } | |
| 328 | |
| 329 private: | |
| 330 v8::Global<v8::Function> function_; | |
| 331 }; | |
| 332 | |
| 333 class SetTimeoutExtension : public v8::Extension { | |
| 334 public: | |
| 335 SetTimeoutExtension() | |
| 336 : v8::Extension("v8_inspector/setTimeout", | |
| 337 "native function setTimeout();") {} | |
| 338 | |
| 339 virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate( | |
| 340 v8::Isolate* isolate, v8::Local<v8::String> name) { | |
| 341 return v8::FunctionTemplate::New(isolate, SetTimeoutExtension::SetTimeout); | |
| 342 } | |
| 343 | |
| 344 private: | |
| 345 static void SetTimeout(const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 346 if (args.Length() != 2 || !args[1]->IsNumber() || | |
| 347 (!args[0]->IsFunction() && !args[0]->IsString()) || | |
| 348 args[1].As<v8::Number>()->Value() != 0.0) { | |
| 349 fprintf(stderr, | |
| 350 "Internal error: only setTimeout(function, 0) is supported."); | |
| 351 Exit(); | |
| 352 } | |
| 353 v8::Isolate* isolate = args.GetIsolate(); | |
| 354 v8::Local<v8::Context> context = isolate->GetCurrentContext(); | |
| 355 std::unique_ptr<TaskRunner::Task> task; | |
| 356 v8_inspector::V8Inspector* inspector = | |
| 357 InspectorClientImpl::InspectorFromContext(context); | |
| 358 if (args[0]->IsFunction()) { | |
| 359 task.reset(new SetTimeoutTask(isolate, | |
| 360 v8::Local<v8::Function>::Cast(args[0]), | |
| 361 "setTimeout", inspector)); | |
| 362 } else { | |
| 363 task.reset(new ExecuteStringTask( | |
| 364 ToVector(args[0].As<v8::String>()), v8::String::Empty(isolate), | |
| 365 v8::Integer::New(isolate, 0), v8::Integer::New(isolate, 0), | |
| 366 v8::Boolean::New(isolate, false), "setTimeout", inspector)); | |
| 367 } | |
| 368 TaskRunner::FromContext(context)->Append(task.release()); | |
| 369 } | |
| 370 }; | |
| 371 | |
| 372 bool StrictAccessCheck(v8::Local<v8::Context> accessing_context, | |
| 373 v8::Local<v8::Object> accessed_object, | |
| 374 v8::Local<v8::Value> data) { | |
| 375 CHECK(accessing_context.IsEmpty()); | |
| 376 return accessing_context.IsEmpty(); | |
| 377 } | |
| 378 | |
| 379 class InspectorExtension : public v8::Extension { | |
| 380 public: | |
| 381 InspectorExtension() | |
| 382 : v8::Extension("v8_inspector/inspector", | |
| 383 "native function attachInspector();" | |
| 384 "native function detachInspector();" | |
| 385 "native function setMaxAsyncTaskStacks();" | |
| 386 "native function dumpAsyncTaskStacksStateForTest();" | |
| 387 "native function breakProgram();" | |
| 388 "native function createObjectWithStrictCheck();" | |
| 389 "native function callWithScheduledBreak();" | |
| 390 "native function allowAccessorFormatting();") {} | |
| 391 | |
| 392 virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate( | |
| 393 v8::Isolate* isolate, v8::Local<v8::String> name) { | |
| 394 v8::Local<v8::Context> context = isolate->GetCurrentContext(); | |
| 395 if (name->Equals(context, | |
| 396 v8::String::NewFromUtf8(isolate, "attachInspector", | |
| 397 v8::NewStringType::kNormal) | |
| 398 .ToLocalChecked()) | |
| 399 .FromJust()) { | |
| 400 return v8::FunctionTemplate::New(isolate, InspectorExtension::Attach); | |
| 401 } else if (name->Equals(context, | |
| 402 v8::String::NewFromUtf8(isolate, "detachInspector", | |
| 403 v8::NewStringType::kNormal) | |
| 404 .ToLocalChecked()) | |
| 405 .FromJust()) { | |
| 406 return v8::FunctionTemplate::New(isolate, InspectorExtension::Detach); | |
| 407 } else if (name->Equals(context, v8::String::NewFromUtf8( | |
| 408 isolate, "setMaxAsyncTaskStacks", | |
| 409 v8::NewStringType::kNormal) | |
| 410 .ToLocalChecked()) | |
| 411 .FromJust()) { | |
| 412 return v8::FunctionTemplate::New( | |
| 413 isolate, InspectorExtension::SetMaxAsyncTaskStacks); | |
| 414 } else if (name->Equals(context, | |
| 415 v8::String::NewFromUtf8( | |
| 416 isolate, "dumpAsyncTaskStacksStateForTest", | |
| 417 v8::NewStringType::kNormal) | |
| 418 .ToLocalChecked()) | |
| 419 .FromJust()) { | |
| 420 return v8::FunctionTemplate::New( | |
| 421 isolate, InspectorExtension::DumpAsyncTaskStacksStateForTest); | |
| 422 } else if (name->Equals(context, | |
| 423 v8::String::NewFromUtf8(isolate, "breakProgram", | |
| 424 v8::NewStringType::kNormal) | |
| 425 .ToLocalChecked()) | |
| 426 .FromJust()) { | |
| 427 return v8::FunctionTemplate::New(isolate, | |
| 428 InspectorExtension::BreakProgram); | |
| 429 } else if (name->Equals(context, v8::String::NewFromUtf8( | |
| 430 isolate, "createObjectWithStrictCheck", | |
| 431 v8::NewStringType::kNormal) | |
| 432 .ToLocalChecked()) | |
| 433 .FromJust()) { | |
| 434 return v8::FunctionTemplate::New( | |
| 435 isolate, InspectorExtension::CreateObjectWithStrictCheck); | |
| 436 } else if (name->Equals(context, v8::String::NewFromUtf8( | |
| 437 isolate, "callWithScheduledBreak", | |
| 438 v8::NewStringType::kNormal) | |
| 439 .ToLocalChecked()) | |
| 440 .FromJust()) { | |
| 441 return v8::FunctionTemplate::New( | |
| 442 isolate, InspectorExtension::CallWithScheduledBreak); | |
| 443 } else if (name->Equals(context, v8::String::NewFromUtf8( | |
| 444 isolate, "allowAccessorFormatting", | |
| 445 v8::NewStringType::kNormal) | |
| 446 .ToLocalChecked()) | |
| 447 .FromJust()) { | |
| 448 return v8::FunctionTemplate::New( | |
| 449 isolate, InspectorExtension::AllowAccessorFormatting); | |
| 450 } | |
| 451 return v8::Local<v8::FunctionTemplate>(); | |
| 452 } | |
| 453 | |
| 454 private: | |
| 455 static void Attach(const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 456 v8::Isolate* isolate = args.GetIsolate(); | |
| 457 v8::Local<v8::Context> context = isolate->GetCurrentContext(); | |
| 458 v8_inspector::V8Inspector* inspector = | |
| 459 InspectorClientImpl::InspectorFromContext(context); | |
| 460 if (!inspector) { | |
| 461 fprintf(stderr, "Inspector client not found - cannot attach!"); | |
| 462 Exit(); | |
| 463 } | |
| 464 inspector->contextCreated( | |
| 465 v8_inspector::V8ContextInfo(context, 1, v8_inspector::StringView())); | |
| 466 } | |
| 467 | |
| 468 static void Detach(const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 469 v8::Isolate* isolate = args.GetIsolate(); | |
| 470 v8::Local<v8::Context> context = isolate->GetCurrentContext(); | |
| 471 v8_inspector::V8Inspector* inspector = | |
| 472 InspectorClientImpl::InspectorFromContext(context); | |
| 473 if (!inspector) { | |
| 474 fprintf(stderr, "Inspector client not found - cannot detach!"); | |
| 475 Exit(); | |
| 476 } | |
| 477 inspector->contextDestroyed(context); | |
| 478 } | |
| 479 | |
| 480 static void SetMaxAsyncTaskStacks( | |
| 481 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 482 if (args.Length() != 1 || !args[0]->IsInt32()) { | |
| 483 fprintf(stderr, "Internal error: setMaxAsyncTaskStacks(max)."); | |
| 484 Exit(); | |
| 485 } | |
| 486 v8_inspector::V8Inspector* inspector = | |
| 487 InspectorClientImpl::InspectorFromContext( | |
| 488 args.GetIsolate()->GetCurrentContext()); | |
| 489 CHECK(inspector); | |
| 490 v8_inspector::SetMaxAsyncTaskStacksForTest( | |
| 491 inspector, args[0].As<v8::Int32>()->Value()); | |
| 492 } | |
| 493 | |
| 494 static void DumpAsyncTaskStacksStateForTest( | |
| 495 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 496 if (args.Length() != 0) { | |
| 497 fprintf(stderr, "Internal error: dumpAsyncTaskStacksStateForTest()."); | |
| 498 Exit(); | |
| 499 } | |
| 500 v8_inspector::V8Inspector* inspector = | |
| 501 InspectorClientImpl::InspectorFromContext( | |
| 502 args.GetIsolate()->GetCurrentContext()); | |
| 503 CHECK(inspector); | |
| 504 v8_inspector::DumpAsyncTaskStacksStateForTest(inspector); | |
| 505 } | |
| 506 | |
| 507 static void BreakProgram(const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 508 if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsString()) { | |
| 509 fprintf(stderr, "Internal error: breakProgram('reason', 'details')."); | |
| 510 Exit(); | |
| 511 } | |
| 512 v8_inspector::V8InspectorSession* session = | |
| 513 InspectorClientImpl::SessionFromContext( | |
| 514 args.GetIsolate()->GetCurrentContext()); | |
| 515 CHECK(session); | |
| 516 | |
| 517 v8::internal::Vector<uint16_t> reason = ToVector(args[0].As<v8::String>()); | |
| 518 v8_inspector::StringView reason_view(reason.start(), reason.length()); | |
| 519 v8::internal::Vector<uint16_t> details = ToVector(args[1].As<v8::String>()); | |
| 520 v8_inspector::StringView details_view(details.start(), details.length()); | |
| 521 session->breakProgram(reason_view, details_view); | |
| 522 } | |
| 523 | |
| 524 static void CreateObjectWithStrictCheck( | |
| 525 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 526 if (args.Length() != 0) { | |
| 527 fprintf(stderr, "Internal error: createObjectWithStrictCheck()."); | |
| 528 Exit(); | |
| 529 } | |
| 530 v8::Local<v8::ObjectTemplate> templ = | |
| 531 v8::ObjectTemplate::New(args.GetIsolate()); | |
| 532 templ->SetAccessCheckCallback(&StrictAccessCheck); | |
| 533 args.GetReturnValue().Set( | |
| 534 templ->NewInstance(args.GetIsolate()->GetCurrentContext()) | |
| 535 .ToLocalChecked()); | |
| 536 } | |
| 537 | |
| 538 static void CallWithScheduledBreak( | |
| 539 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 540 if (args.Length() != 3 || !args[0]->IsFunction() || !args[1]->IsString() || | |
| 541 !args[2]->IsString()) { | |
| 542 fprintf(stderr, "Internal error: breakProgram('reason', 'details')."); | |
| 543 Exit(); | |
| 544 } | |
| 545 v8_inspector::V8InspectorSession* session = | |
| 546 InspectorClientImpl::SessionFromContext( | |
| 547 args.GetIsolate()->GetCurrentContext()); | |
| 548 CHECK(session); | |
| 549 | |
| 550 v8::internal::Vector<uint16_t> reason = ToVector(args[1].As<v8::String>()); | |
| 551 v8_inspector::StringView reason_view(reason.start(), reason.length()); | |
| 552 v8::internal::Vector<uint16_t> details = ToVector(args[2].As<v8::String>()); | |
| 553 v8_inspector::StringView details_view(details.start(), details.length()); | |
| 554 session->schedulePauseOnNextStatement(reason_view, details_view); | |
| 555 v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext(); | |
| 556 v8::MaybeLocal<v8::Value> result; | |
| 557 result = args[0].As<v8::Function>()->Call(context, context->Global(), 0, | |
| 558 nullptr); | |
| 559 session->cancelPauseOnNextStatement(); | |
| 560 } | |
| 561 | |
| 562 static void AllowAccessorFormatting( | |
| 563 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
| 564 if (args.Length() != 1 || !args[0]->IsObject()) { | |
| 565 fprintf(stderr, "Internal error: allowAccessorFormatting('object')."); | |
| 566 Exit(); | |
| 567 } | |
| 568 v8::Local<v8::Object> object = args[0].As<v8::Object>(); | |
| 569 v8::Isolate* isolate = args.GetIsolate(); | |
| 570 v8::Local<v8::Private> shouldFormatAccessorsPrivate = v8::Private::ForApi( | |
| 571 isolate, v8::String::NewFromUtf8(isolate, "allowAccessorFormatting", | |
| 572 v8::NewStringType::kNormal) | |
| 573 .ToLocalChecked()); | |
| 574 object | |
| 575 ->SetPrivate(isolate->GetCurrentContext(), shouldFormatAccessorsPrivate, | |
| 576 v8::Null(isolate)) | |
| 577 .ToChecked(); | |
| 578 } | |
| 579 }; | |
| 580 | |
| 581 v8::Local<v8::String> ToString(v8::Isolate* isolate, | 531 v8::Local<v8::String> ToString(v8::Isolate* isolate, |
| 582 const v8_inspector::StringView& string) { | 532 const v8_inspector::StringView& string) { |
| 583 if (string.is8Bit()) | 533 if (string.is8Bit()) |
| 584 return v8::String::NewFromOneByte(isolate, string.characters8(), | 534 return v8::String::NewFromOneByte(isolate, string.characters8(), |
| 585 v8::NewStringType::kNormal, | 535 v8::NewStringType::kNormal, |
| 586 static_cast<int>(string.length())) | 536 static_cast<int>(string.length())) |
| 587 .ToLocalChecked(); | 537 .ToLocalChecked(); |
| 588 else | 538 else |
| 589 return v8::String::NewFromTwoByte(isolate, string.characters16(), | 539 return v8::String::NewFromTwoByte(isolate, string.characters16(), |
| 590 v8::NewStringType::kNormal, | 540 v8::NewStringType::kNormal, |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 627 } // namespace | 577 } // namespace |
| 628 | 578 |
| 629 int main(int argc, char* argv[]) { | 579 int main(int argc, char* argv[]) { |
| 630 v8::V8::InitializeICUDefaultLocation(argv[0]); | 580 v8::V8::InitializeICUDefaultLocation(argv[0]); |
| 631 v8::Platform* platform = v8::platform::CreateDefaultPlatform(); | 581 v8::Platform* platform = v8::platform::CreateDefaultPlatform(); |
| 632 v8::V8::InitializePlatform(platform); | 582 v8::V8::InitializePlatform(platform); |
| 633 v8::V8::SetFlagsFromCommandLine(&argc, argv, true); | 583 v8::V8::SetFlagsFromCommandLine(&argc, argv, true); |
| 634 v8::V8::InitializeExternalStartupData(argv[0]); | 584 v8::V8::InitializeExternalStartupData(argv[0]); |
| 635 v8::V8::Initialize(); | 585 v8::V8::Initialize(); |
| 636 | 586 |
| 637 SetTimeoutExtension set_timeout_extension; | |
| 638 v8::RegisterExtension(&set_timeout_extension); | |
| 639 InspectorExtension inspector_extension; | |
| 640 v8::RegisterExtension(&inspector_extension); | |
| 641 SendMessageToBackendExtension send_message_to_backend_extension; | |
| 642 v8::RegisterExtension(&send_message_to_backend_extension); | |
| 643 | |
| 644 v8::base::Semaphore ready_semaphore(0); | 587 v8::base::Semaphore ready_semaphore(0); |
| 645 | 588 |
| 646 const char* backend_extensions[] = {"v8_inspector/setTimeout", | 589 TaskRunner::SetupGlobalTasks backend_extensions; |
| 647 "v8_inspector/inspector"}; | 590 backend_extensions.emplace_back(new SetTimeoutExtension()); |
| 648 v8::ExtensionConfiguration backend_configuration( | 591 backend_extensions.emplace_back(new InspectorExtension()); |
| 649 arraysize(backend_extensions), backend_extensions); | 592 TaskRunner backend_runner(std::move(backend_extensions), false, |
| 650 TaskRunner backend_runner(&backend_configuration, false, &ready_semaphore); | 593 &ready_semaphore); |
| 651 ready_semaphore.Wait(); | 594 ready_semaphore.Wait(); |
| 652 SendMessageToBackendExtension::set_backend_task_runner(&backend_runner); | 595 SendMessageToBackendExtension::set_backend_task_runner(&backend_runner); |
| 653 UtilsExtension::set_backend_task_runner(&backend_runner); | 596 UtilsExtension::set_backend_task_runner(&backend_runner); |
| 654 | 597 |
| 655 const char* frontend_extensions[] = {"v8_inspector/frontend"}; | 598 TaskRunner::SetupGlobalTasks frontend_extensions; |
| 656 v8::ExtensionConfiguration frontend_configuration( | 599 frontend_extensions.emplace_back(new UtilsExtension()); |
| 657 arraysize(frontend_extensions), frontend_extensions); | 600 frontend_extensions.emplace_back(new SendMessageToBackendExtension()); |
| 658 TaskRunner frontend_runner(&frontend_configuration, true, &ready_semaphore); | 601 TaskRunner frontend_runner(std::move(frontend_extensions), true, |
| 602 &ready_semaphore); | |
| 659 ready_semaphore.Wait(); | 603 ready_semaphore.Wait(); |
| 660 frontend_runner.Append(new UtilsExtension()); | |
| 661 | 604 |
| 662 FrontendChannelImpl frontend_channel(&frontend_runner); | 605 FrontendChannelImpl frontend_channel(&frontend_runner); |
| 663 InspectorClientImpl inspector_client(&backend_runner, &frontend_channel, | 606 InspectorClientImpl inspector_client(&backend_runner, &frontend_channel, |
| 664 &ready_semaphore); | 607 &ready_semaphore); |
| 665 ready_semaphore.Wait(); | 608 ready_semaphore.Wait(); |
| 666 UtilsExtension::set_inspector_client(&inspector_client); | 609 UtilsExtension::set_inspector_client(&inspector_client); |
| 667 | 610 |
| 668 task_runners.push_back(&frontend_runner); | 611 task_runners.push_back(&frontend_runner); |
| 669 task_runners.push_back(&backend_runner); | 612 task_runners.push_back(&backend_runner); |
| 670 | 613 |
| 671 for (int i = 1; i < argc; ++i) { | 614 for (int i = 1; i < argc; ++i) { |
| 672 // Ignore unknown flags. | 615 // Ignore unknown flags. |
| 673 if (argv[i][0] == '-') continue; | 616 if (argv[i][0] == '-') continue; |
| 674 | 617 |
| 675 bool exists = false; | 618 bool exists = false; |
| 676 v8::internal::Vector<const char> chars = | 619 v8::internal::Vector<const char> chars = |
| 677 v8::internal::ReadFile(argv[i], &exists, true); | 620 v8::internal::ReadFile(argv[i], &exists, true); |
| 678 if (!exists) { | 621 if (!exists) { |
| 679 fprintf(stderr, "Internal error: script file doesn't exists: %s\n", | 622 fprintf(stderr, "Internal error: script file doesn't exists: %s\n", |
| 680 argv[i]); | 623 argv[i]); |
| 681 Exit(); | 624 Exit(); |
| 682 } | 625 } |
| 683 frontend_runner.Append(new ExecuteStringTask(chars)); | 626 frontend_runner.Append(new ExecuteStringTask(chars)); |
| 684 } | 627 } |
| 685 | 628 |
| 686 frontend_runner.Join(); | 629 frontend_runner.Join(); |
| 687 backend_runner.Join(); | 630 backend_runner.Join(); |
| 688 return 0; | 631 return 0; |
| 689 } | 632 } |
| OLD | NEW |