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 |