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 #include "src/inspector/v8-debugger.h" | 5 #include "src/inspector/v8-debugger.h" |
6 | 6 |
7 #include "src/inspector/debugger-script.h" | 7 #include "src/inspector/debugger-script.h" |
8 #include "src/inspector/inspected-context.h" | 8 #include "src/inspector/inspected-context.h" |
9 #include "src/inspector/protocol/Protocol.h" | 9 #include "src/inspector/protocol/Protocol.h" |
10 #include "src/inspector/script-breakpoint.h" | 10 #include "src/inspector/script-breakpoint.h" |
11 #include "src/inspector/string-util.h" | 11 #include "src/inspector/string-util.h" |
12 #include "src/inspector/v8-debugger-agent-impl.h" | 12 #include "src/inspector/v8-debugger-agent-impl.h" |
13 #include "src/inspector/v8-inspector-impl.h" | 13 #include "src/inspector/v8-inspector-impl.h" |
14 #include "src/inspector/v8-internal-value-type.h" | 14 #include "src/inspector/v8-internal-value-type.h" |
15 #include "src/inspector/v8-stack-trace-impl.h" | 15 #include "src/inspector/v8-stack-trace-impl.h" |
16 #include "src/inspector/v8-value-copier.h" | 16 #include "src/inspector/v8-value-copier.h" |
17 | 17 |
18 #include "include/v8-util.h" | 18 #include "include/v8-util.h" |
19 | 19 |
20 namespace v8_inspector { | 20 namespace v8_inspector { |
21 | 21 |
22 namespace { | 22 namespace { |
23 static const char v8AsyncTaskEventEnqueue[] = "enqueue"; | |
24 static const char v8AsyncTaskEventEnqueueRecurring[] = "enqueueRecurring"; | |
25 static const char v8AsyncTaskEventWillHandle[] = "willHandle"; | |
26 static const char v8AsyncTaskEventDidHandle[] = "didHandle"; | |
27 static const char v8AsyncTaskEventCancel[] = "cancel"; | |
28 | 23 |
29 // Based on DevTools frontend measurement, with asyncCallStackDepth = 4, | 24 // Based on DevTools frontend measurement, with asyncCallStackDepth = 4, |
30 // average async call stack tail requires ~1 Kb. Let's reserve ~ 128 Mb | 25 // average async call stack tail requires ~1 Kb. Let's reserve ~ 128 Mb |
31 // for async stacks. | 26 // for async stacks. |
32 static const int kMaxAsyncTaskStacks = 128 * 1024; | 27 static const int kMaxAsyncTaskStacks = 128 * 1024; |
33 | 28 |
34 inline v8::Local<v8::Boolean> v8Boolean(bool value, v8::Isolate* isolate) { | 29 inline v8::Local<v8::Boolean> v8Boolean(bool value, v8::Isolate* isolate) { |
35 return value ? v8::True(isolate) : v8::False(isolate); | 30 return value ? v8::True(isolate) : v8::False(isolate); |
36 } | 31 } |
37 | 32 |
(...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
528 .ToLocalChecked(); | 523 .ToLocalChecked(); |
529 DCHECK(!getterValue.IsEmpty() && getterValue->IsFunction()); | 524 DCHECK(!getterValue.IsEmpty() && getterValue->IsFunction()); |
530 return v8::Local<v8::Function>::Cast(getterValue) | 525 return v8::Local<v8::Function>::Cast(getterValue) |
531 ->Call(m_isolate->GetCurrentContext(), object, 0, nullptr) | 526 ->Call(m_isolate->GetCurrentContext(), object, 0, nullptr) |
532 .ToLocalChecked(); | 527 .ToLocalChecked(); |
533 } | 528 } |
534 | 529 |
535 void V8Debugger::handleV8DebugEvent( | 530 void V8Debugger::handleV8DebugEvent( |
536 const v8::debug::EventDetails& eventDetails) { | 531 const v8::debug::EventDetails& eventDetails) { |
537 if (!enabled()) return; | 532 if (!enabled()) return; |
| 533 v8::HandleScope scope(m_isolate); |
| 534 |
538 v8::DebugEvent event = eventDetails.GetEvent(); | 535 v8::DebugEvent event = eventDetails.GetEvent(); |
539 if (event != v8::AsyncTaskEvent && event != v8::Break && | 536 if (event != v8::AsyncTaskEvent && event != v8::Break && |
540 event != v8::Exception && event != v8::AfterCompile && | 537 event != v8::Exception && event != v8::AfterCompile && |
541 event != v8::CompileError) | 538 event != v8::CompileError) |
542 return; | 539 return; |
543 | 540 |
544 v8::Local<v8::Context> eventContext = eventDetails.GetEventContext(); | |
545 DCHECK(!eventContext.IsEmpty()); | |
546 | |
547 if (event == v8::AsyncTaskEvent) { | 541 if (event == v8::AsyncTaskEvent) { |
548 v8::HandleScope scope(m_isolate); | 542 handleV8AsyncTaskEvent(eventDetails.GetEventData()); |
549 handleV8AsyncTaskEvent(eventContext, eventDetails.GetExecutionState(), | |
550 eventDetails.GetEventData()); | |
551 return; | 543 return; |
552 } | 544 } |
553 | 545 |
| 546 v8::Local<v8::Context> eventContext = eventDetails.GetEventContext(); |
| 547 DCHECK(!eventContext.IsEmpty()); |
554 V8DebuggerAgentImpl* agent = m_inspector->enabledDebuggerAgentForGroup( | 548 V8DebuggerAgentImpl* agent = m_inspector->enabledDebuggerAgentForGroup( |
555 m_inspector->contextGroupId(eventContext)); | 549 m_inspector->contextGroupId(eventContext)); |
556 if (!agent) return; | 550 if (!agent) return; |
557 | 551 |
558 v8::HandleScope scope(m_isolate); | |
559 if (event == v8::AfterCompile || event == v8::CompileError) { | 552 if (event == v8::AfterCompile || event == v8::CompileError) { |
560 v8::Context::Scope contextScope(debuggerContext()); | 553 v8::Context::Scope contextScope(debuggerContext()); |
561 // Determine if the script is a wasm script. | 554 // Determine if the script is a wasm script. |
562 v8::Local<v8::Value> scriptMirror = | 555 v8::Local<v8::Value> scriptMirror = |
563 callInternalGetterFunction(eventDetails.GetEventData(), "script"); | 556 callInternalGetterFunction(eventDetails.GetEventData(), "script"); |
564 DCHECK(scriptMirror->IsObject()); | 557 DCHECK(scriptMirror->IsObject()); |
565 v8::Local<v8::Value> scriptWrapper = | 558 v8::Local<v8::Value> scriptWrapper = |
566 callInternalGetterFunction(scriptMirror.As<v8::Object>(), "value"); | 559 callInternalGetterFunction(scriptMirror.As<v8::Object>(), "value"); |
567 DCHECK(scriptWrapper->IsObject()); | 560 DCHECK(scriptWrapper->IsObject()); |
568 v8::Local<v8::debug::Script> script; | 561 v8::Local<v8::debug::Script> script; |
(...skipping 27 matching lines...) Expand all Loading... |
596 v8::Local<v8::Value> hitBreakpoints; | 589 v8::Local<v8::Value> hitBreakpoints; |
597 if (!callDebuggerMethod("getBreakpointNumbers", 1, argv) | 590 if (!callDebuggerMethod("getBreakpointNumbers", 1, argv) |
598 .ToLocal(&hitBreakpoints)) | 591 .ToLocal(&hitBreakpoints)) |
599 return; | 592 return; |
600 DCHECK(hitBreakpoints->IsArray()); | 593 DCHECK(hitBreakpoints->IsArray()); |
601 handleProgramBreak(eventContext, eventDetails.GetExecutionState(), | 594 handleProgramBreak(eventContext, eventDetails.GetExecutionState(), |
602 v8::Local<v8::Value>(), hitBreakpoints.As<v8::Array>()); | 595 v8::Local<v8::Value>(), hitBreakpoints.As<v8::Array>()); |
603 } | 596 } |
604 } | 597 } |
605 | 598 |
606 void V8Debugger::handleV8AsyncTaskEvent(v8::Local<v8::Context> context, | 599 void V8Debugger::handleV8AsyncTaskEvent(v8::Local<v8::Object> eventData) { |
607 v8::Local<v8::Object> executionState, | |
608 v8::Local<v8::Object> eventData) { | |
609 if (!m_maxAsyncCallStackDepth) return; | 600 if (!m_maxAsyncCallStackDepth) return; |
610 | 601 |
611 String16 type = toProtocolStringWithTypeCheck( | 602 // TODO(kozyatinskiy): remove usage of current context as soon as async event |
612 callInternalGetterFunction(eventData, "type")); | 603 // is migrated to pure C++ API. |
| 604 v8::debug::PromiseDebugActionType type = |
| 605 static_cast<v8::debug::PromiseDebugActionType>( |
| 606 eventData |
| 607 ->Get(m_isolate->GetCurrentContext(), |
| 608 toV8StringInternalized(m_isolate, "type_")) |
| 609 .ToLocalChecked() |
| 610 ->ToInteger(m_isolate->GetCurrentContext()) |
| 611 .ToLocalChecked() |
| 612 ->Value()); |
613 String16 name = toProtocolStringWithTypeCheck( | 613 String16 name = toProtocolStringWithTypeCheck( |
614 callInternalGetterFunction(eventData, "name")); | 614 eventData |
615 int id = static_cast<int>(callInternalGetterFunction(eventData, "id") | 615 ->Get(m_isolate->GetCurrentContext(), |
616 ->ToInteger(context) | 616 toV8StringInternalized(m_isolate, "name_")) |
| 617 .ToLocalChecked()); |
| 618 int id = static_cast<int>(eventData |
| 619 ->Get(m_isolate->GetCurrentContext(), |
| 620 toV8StringInternalized(m_isolate, "id_")) |
| 621 .ToLocalChecked() |
| 622 ->ToInteger(m_isolate->GetCurrentContext()) |
617 .ToLocalChecked() | 623 .ToLocalChecked() |
618 ->Value()); | 624 ->Value()); |
619 // Async task events from Promises are given misaligned pointers to prevent | 625 // Async task events from Promises are given misaligned pointers to prevent |
620 // from overlapping with other Blink task identifiers. There is a single | 626 // from overlapping with other Blink task identifiers. There is a single |
621 // namespace of such ids, managed by src/js/promise.js. | 627 // namespace of such ids, managed by src/js/promise.js. |
622 void* ptr = reinterpret_cast<void*>(id * 2 + 1); | 628 void* ptr = reinterpret_cast<void*>(id * 2 + 1); |
623 if (type == v8AsyncTaskEventEnqueue) | 629 switch (type) { |
624 asyncTaskScheduled(name, ptr, false); | 630 case v8::debug::kDebugEnqueueRecurring: |
625 else if (type == v8AsyncTaskEventEnqueueRecurring) | 631 asyncTaskScheduled(name, ptr, true); |
626 asyncTaskScheduled(name, ptr, true); | 632 break; |
627 else if (type == v8AsyncTaskEventWillHandle) | 633 case v8::debug::kDebugCancel: |
628 asyncTaskStarted(ptr); | 634 asyncTaskCanceled(ptr); |
629 else if (type == v8AsyncTaskEventDidHandle) | 635 break; |
630 asyncTaskFinished(ptr); | 636 case v8::debug::kDebugWillHandle: |
631 else if (type == v8AsyncTaskEventCancel) | 637 asyncTaskStarted(ptr); |
632 asyncTaskCanceled(ptr); | 638 break; |
633 else | 639 case v8::debug::kDebugDidHandle: |
634 UNREACHABLE(); | 640 asyncTaskFinished(ptr); |
| 641 break; |
| 642 } |
635 } | 643 } |
636 | 644 |
637 V8StackTraceImpl* V8Debugger::currentAsyncCallChain() { | 645 V8StackTraceImpl* V8Debugger::currentAsyncCallChain() { |
638 if (!m_currentStacks.size()) return nullptr; | 646 if (!m_currentStacks.size()) return nullptr; |
639 return m_currentStacks.back().get(); | 647 return m_currentStacks.back().get(); |
640 } | 648 } |
641 | 649 |
642 void V8Debugger::compileDebuggerScript() { | 650 void V8Debugger::compileDebuggerScript() { |
643 if (!m_debuggerScript.IsEmpty()) { | 651 if (!m_debuggerScript.IsEmpty()) { |
644 UNREACHABLE(); | 652 UNREACHABLE(); |
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1002 | 1010 |
1003 size_t stackSize = | 1011 size_t stackSize = |
1004 fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1; | 1012 fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1; |
1005 if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) | 1013 if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) |
1006 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; | 1014 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; |
1007 | 1015 |
1008 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); | 1016 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); |
1009 } | 1017 } |
1010 | 1018 |
1011 } // namespace v8_inspector | 1019 } // namespace v8_inspector |
OLD | NEW |