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" |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 m_wasmTranslation(isolate) {} | 63 m_wasmTranslation(isolate) {} |
64 | 64 |
65 V8Debugger::~V8Debugger() {} | 65 V8Debugger::~V8Debugger() {} |
66 | 66 |
67 void V8Debugger::enable() { | 67 void V8Debugger::enable() { |
68 if (m_enableCount++) return; | 68 if (m_enableCount++) return; |
69 DCHECK(!enabled()); | 69 DCHECK(!enabled()); |
70 v8::HandleScope scope(m_isolate); | 70 v8::HandleScope scope(m_isolate); |
71 v8::debug::SetDebugEventListener(m_isolate, &V8Debugger::v8DebugEventCallback, | 71 v8::debug::SetDebugEventListener(m_isolate, &V8Debugger::v8DebugEventCallback, |
72 v8::External::New(m_isolate, this)); | 72 v8::External::New(m_isolate, this)); |
| 73 v8::debug::SetAsyncTaskListener(m_isolate, &V8Debugger::v8AsyncTaskListener, |
| 74 this); |
73 m_debuggerContext.Reset(m_isolate, v8::debug::GetDebugContext(m_isolate)); | 75 m_debuggerContext.Reset(m_isolate, v8::debug::GetDebugContext(m_isolate)); |
74 v8::debug::ChangeBreakOnException(m_isolate, v8::debug::NoBreakOnException); | 76 v8::debug::ChangeBreakOnException(m_isolate, v8::debug::NoBreakOnException); |
75 m_pauseOnExceptionsState = v8::debug::NoBreakOnException; | 77 m_pauseOnExceptionsState = v8::debug::NoBreakOnException; |
76 compileDebuggerScript(); | 78 compileDebuggerScript(); |
77 } | 79 } |
78 | 80 |
79 void V8Debugger::disable() { | 81 void V8Debugger::disable() { |
80 if (--m_enableCount) return; | 82 if (--m_enableCount) return; |
81 DCHECK(enabled()); | 83 DCHECK(enabled()); |
82 clearBreakpoints(); | 84 clearBreakpoints(); |
83 m_debuggerScript.Reset(); | 85 m_debuggerScript.Reset(); |
84 m_debuggerContext.Reset(); | 86 m_debuggerContext.Reset(); |
85 allAsyncTasksCanceled(); | 87 allAsyncTasksCanceled(); |
86 m_wasmTranslation.Clear(); | 88 m_wasmTranslation.Clear(); |
87 v8::debug::SetDebugEventListener(m_isolate, nullptr); | 89 v8::debug::SetDebugEventListener(m_isolate, nullptr); |
| 90 v8::debug::SetAsyncTaskListener(m_isolate, nullptr, nullptr); |
88 } | 91 } |
89 | 92 |
90 bool V8Debugger::enabled() const { return !m_debuggerScript.IsEmpty(); } | 93 bool V8Debugger::enabled() const { return !m_debuggerScript.IsEmpty(); } |
91 | 94 |
92 void V8Debugger::getCompiledScripts( | 95 void V8Debugger::getCompiledScripts( |
93 int contextGroupId, | 96 int contextGroupId, |
94 std::vector<std::unique_ptr<V8DebuggerScript>>& result) { | 97 std::vector<std::unique_ptr<V8DebuggerScript>>& result) { |
95 v8::HandleScope scope(m_isolate); | 98 v8::HandleScope scope(m_isolate); |
96 v8::PersistentValueVector<v8::debug::Script> scripts(m_isolate); | 99 v8::PersistentValueVector<v8::debug::Script> scripts(m_isolate); |
97 v8::debug::GetLoadedScripts(m_isolate, scripts); | 100 v8::debug::GetLoadedScripts(m_isolate, scripts); |
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
526 ->Call(m_isolate->GetCurrentContext(), object, 0, nullptr) | 529 ->Call(m_isolate->GetCurrentContext(), object, 0, nullptr) |
527 .ToLocalChecked(); | 530 .ToLocalChecked(); |
528 } | 531 } |
529 | 532 |
530 void V8Debugger::handleV8DebugEvent( | 533 void V8Debugger::handleV8DebugEvent( |
531 const v8::debug::EventDetails& eventDetails) { | 534 const v8::debug::EventDetails& eventDetails) { |
532 if (!enabled()) return; | 535 if (!enabled()) return; |
533 v8::HandleScope scope(m_isolate); | 536 v8::HandleScope scope(m_isolate); |
534 | 537 |
535 v8::DebugEvent event = eventDetails.GetEvent(); | 538 v8::DebugEvent event = eventDetails.GetEvent(); |
536 if (event != v8::AsyncTaskEvent && event != v8::Break && | 539 if (event != v8::Break && event != v8::Exception && |
537 event != v8::Exception && event != v8::AfterCompile && | 540 event != v8::AfterCompile && event != v8::CompileError) |
538 event != v8::CompileError) | |
539 return; | 541 return; |
540 | 542 |
541 if (event == v8::AsyncTaskEvent) { | |
542 handleV8AsyncTaskEvent(eventDetails.GetEventData()); | |
543 return; | |
544 } | |
545 | |
546 v8::Local<v8::Context> eventContext = eventDetails.GetEventContext(); | 543 v8::Local<v8::Context> eventContext = eventDetails.GetEventContext(); |
547 DCHECK(!eventContext.IsEmpty()); | 544 DCHECK(!eventContext.IsEmpty()); |
548 V8DebuggerAgentImpl* agent = m_inspector->enabledDebuggerAgentForGroup( | 545 V8DebuggerAgentImpl* agent = m_inspector->enabledDebuggerAgentForGroup( |
549 m_inspector->contextGroupId(eventContext)); | 546 m_inspector->contextGroupId(eventContext)); |
550 if (!agent) return; | 547 if (!agent) return; |
551 | 548 |
552 if (event == v8::AfterCompile || event == v8::CompileError) { | 549 if (event == v8::AfterCompile || event == v8::CompileError) { |
553 v8::Context::Scope contextScope(debuggerContext()); | 550 v8::Context::Scope contextScope(debuggerContext()); |
554 // Determine if the script is a wasm script. | 551 // Determine if the script is a wasm script. |
555 v8::Local<v8::Value> scriptMirror = | 552 v8::Local<v8::Value> scriptMirror = |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
589 v8::Local<v8::Value> hitBreakpoints; | 586 v8::Local<v8::Value> hitBreakpoints; |
590 if (!callDebuggerMethod("getBreakpointNumbers", 1, argv) | 587 if (!callDebuggerMethod("getBreakpointNumbers", 1, argv) |
591 .ToLocal(&hitBreakpoints)) | 588 .ToLocal(&hitBreakpoints)) |
592 return; | 589 return; |
593 DCHECK(hitBreakpoints->IsArray()); | 590 DCHECK(hitBreakpoints->IsArray()); |
594 handleProgramBreak(eventContext, eventDetails.GetExecutionState(), | 591 handleProgramBreak(eventContext, eventDetails.GetExecutionState(), |
595 v8::Local<v8::Value>(), hitBreakpoints.As<v8::Array>()); | 592 v8::Local<v8::Value>(), hitBreakpoints.As<v8::Array>()); |
596 } | 593 } |
597 } | 594 } |
598 | 595 |
599 void V8Debugger::handleV8AsyncTaskEvent(v8::Local<v8::Object> eventData) { | 596 void V8Debugger::v8AsyncTaskListener(v8::debug::PromiseDebugActionType type, |
600 if (!m_maxAsyncCallStackDepth) return; | 597 int id, void* data) { |
601 | 598 V8Debugger* debugger = static_cast<V8Debugger*>(data); |
602 // TODO(kozyatinskiy): remove usage of current context as soon as async event | 599 if (!debugger->m_maxAsyncCallStackDepth) return; |
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 int id = static_cast<int>(eventData | |
614 ->Get(m_isolate->GetCurrentContext(), | |
615 toV8StringInternalized(m_isolate, "id_")) | |
616 .ToLocalChecked() | |
617 ->ToInteger(m_isolate->GetCurrentContext()) | |
618 .ToLocalChecked() | |
619 ->Value()); | |
620 // Async task events from Promises are given misaligned pointers to prevent | 600 // Async task events from Promises are given misaligned pointers to prevent |
621 // from overlapping with other Blink task identifiers. There is a single | 601 // from overlapping with other Blink task identifiers. There is a single |
622 // namespace of such ids, managed by src/js/promise.js. | 602 // namespace of such ids, managed by src/js/promise.js. |
623 void* ptr = reinterpret_cast<void*>(id * 2 + 1); | 603 void* ptr = reinterpret_cast<void*>(id * 2 + 1); |
624 switch (type) { | 604 switch (type) { |
625 case v8::debug::kDebugEnqueueAsyncFunction: | 605 case v8::debug::kDebugEnqueueAsyncFunction: |
626 asyncTaskScheduled("async function", ptr, true); | 606 debugger->asyncTaskScheduled("async function", ptr, true); |
627 break; | 607 break; |
628 case v8::debug::kDebugEnqueuePromiseResolve: | 608 case v8::debug::kDebugEnqueuePromiseResolve: |
629 asyncTaskScheduled("Promise.resolve", ptr, true); | 609 debugger->asyncTaskScheduled("Promise.resolve", ptr, true); |
630 break; | 610 break; |
631 case v8::debug::kDebugEnqueuePromiseReject: | 611 case v8::debug::kDebugEnqueuePromiseReject: |
632 asyncTaskScheduled("Promise.reject", ptr, true); | 612 debugger->asyncTaskScheduled("Promise.reject", ptr, true); |
633 break; | 613 break; |
634 case v8::debug::kDebugEnqueuePromiseResolveThenableJob: | 614 case v8::debug::kDebugEnqueuePromiseResolveThenableJob: |
635 asyncTaskScheduled("PromiseResolveThenableJob", ptr, true); | 615 debugger->asyncTaskScheduled("PromiseResolveThenableJob", ptr, true); |
636 break; | 616 break; |
637 case v8::debug::kDebugPromiseCollected: | 617 case v8::debug::kDebugPromiseCollected: |
638 asyncTaskCanceled(ptr); | 618 debugger->asyncTaskCanceled(ptr); |
639 break; | 619 break; |
640 case v8::debug::kDebugWillHandle: | 620 case v8::debug::kDebugWillHandle: |
641 asyncTaskStarted(ptr); | 621 debugger->asyncTaskStarted(ptr); |
642 break; | 622 break; |
643 case v8::debug::kDebugDidHandle: | 623 case v8::debug::kDebugDidHandle: |
644 asyncTaskFinished(ptr); | 624 debugger->asyncTaskFinished(ptr); |
645 break; | 625 break; |
646 } | 626 } |
647 } | 627 } |
648 | 628 |
649 V8StackTraceImpl* V8Debugger::currentAsyncCallChain() { | 629 V8StackTraceImpl* V8Debugger::currentAsyncCallChain() { |
650 if (!m_currentStacks.size()) return nullptr; | 630 if (!m_currentStacks.size()) return nullptr; |
651 return m_currentStacks.back().get(); | 631 return m_currentStacks.back().get(); |
652 } | 632 } |
653 | 633 |
654 void V8Debugger::compileDebuggerScript() { | 634 void V8Debugger::compileDebuggerScript() { |
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1014 | 994 |
1015 size_t stackSize = | 995 size_t stackSize = |
1016 fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1; | 996 fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1; |
1017 if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) | 997 if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) |
1018 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; | 998 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; |
1019 | 999 |
1020 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); | 1000 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); |
1021 } | 1001 } |
1022 | 1002 |
1023 } // namespace v8_inspector | 1003 } // namespace v8_inspector |
OLD | NEW |