| 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 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 340 v8::debug::DebugBreak(m_isolate); | 340 v8::debug::DebugBreak(m_isolate); |
| 341 else | 341 else |
| 342 v8::debug::CancelDebugBreak(m_isolate); | 342 v8::debug::CancelDebugBreak(m_isolate); |
| 343 } | 343 } |
| 344 | 344 |
| 345 bool V8Debugger::canBreakProgram() { | 345 bool V8Debugger::canBreakProgram() { |
| 346 if (!m_breakpointsActivated) return false; | 346 if (!m_breakpointsActivated) return false; |
| 347 return !v8::debug::AllFramesOnStackAreBlackboxed(m_isolate); | 347 return !v8::debug::AllFramesOnStackAreBlackboxed(m_isolate); |
| 348 } | 348 } |
| 349 | 349 |
| 350 bool V8Debugger::breakProgram(int targetContextGroupId) { | 350 void V8Debugger::breakProgram(int targetContextGroupId) { |
| 351 // Don't allow nested breaks. | 351 // Don't allow nested breaks. |
| 352 if (isPaused()) return true; | 352 if (isPaused()) return; |
| 353 if (!canBreakProgram()) return true; | 353 if (!canBreakProgram()) return; |
| 354 DCHECK(targetContextGroupId); | 354 DCHECK(targetContextGroupId); |
| 355 m_targetContextGroupId = targetContextGroupId; | 355 m_targetContextGroupId = targetContextGroupId; |
| 356 v8::debug::BreakRightNow(m_isolate); | 356 v8::debug::BreakRightNow(m_isolate); |
| 357 V8InspectorSessionImpl* session = | |
| 358 m_inspector->sessionForContextGroup(targetContextGroupId); | |
| 359 return session && session->debuggerAgent()->enabled(); | |
| 360 } | 357 } |
| 361 | 358 |
| 362 void V8Debugger::continueProgram(int targetContextGroupId) { | 359 void V8Debugger::continueProgram(int targetContextGroupId) { |
| 363 if (m_pausedContextGroupId != targetContextGroupId) return; | 360 if (m_pausedContextGroupId != targetContextGroupId) return; |
| 364 if (isPaused()) m_inspector->client()->quitMessageLoopOnPause(); | 361 if (isPaused()) m_inspector->client()->quitMessageLoopOnPause(); |
| 365 m_pausedContext.Clear(); | 362 m_pausedContext.Clear(); |
| 366 m_executionState.Clear(); | 363 m_executionState.Clear(); |
| 367 } | 364 } |
| 368 | 365 |
| 369 void V8Debugger::stepIntoStatement(int targetContextGroupId) { | 366 void V8Debugger::stepIntoStatement(int targetContextGroupId) { |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 593 v8::debug::PrepareStep(m_isolate, v8::debug::StepOut); | 590 v8::debug::PrepareStep(m_isolate, v8::debug::StepOut); |
| 594 return; | 591 return; |
| 595 } | 592 } |
| 596 m_targetContextGroupId = 0; | 593 m_targetContextGroupId = 0; |
| 597 if (m_stepIntoAsyncCallback) { | 594 if (m_stepIntoAsyncCallback) { |
| 598 m_stepIntoAsyncCallback->sendFailure( | 595 m_stepIntoAsyncCallback->sendFailure( |
| 599 Response::Error("No async tasks were scheduled before pause.")); | 596 Response::Error("No async tasks were scheduled before pause.")); |
| 600 m_stepIntoAsyncCallback.reset(); | 597 m_stepIntoAsyncCallback.reset(); |
| 601 } | 598 } |
| 602 m_breakRequested = false; | 599 m_breakRequested = false; |
| 603 V8InspectorSessionImpl* session = | 600 |
| 604 m_inspector->sessionForContextGroup(contextGroupId); | 601 bool scheduledOOMBreak = m_scheduledOOMBreak; |
| 605 if (!session || !session->debuggerAgent()->enabled()) return; | 602 auto agentCheck = [&scheduledOOMBreak](V8DebuggerAgentImpl* agent) { |
| 606 if (!m_scheduledOOMBreak && session->debuggerAgent()->skipAllPauses()) return; | 603 return agent->enabled() && (scheduledOOMBreak || !agent->skipAllPauses()); |
| 604 }; |
| 605 |
| 606 bool hasAgents = false; |
| 607 m_inspector->forEachSession( |
| 608 contextGroupId, |
| 609 [&agentCheck, &hasAgents](V8InspectorSessionImpl* session) { |
| 610 if (agentCheck(session->debuggerAgent())) hasAgents = true; |
| 611 }); |
| 612 if (!hasAgents) return; |
| 607 | 613 |
| 608 std::vector<String16> breakpointIds; | 614 std::vector<String16> breakpointIds; |
| 609 if (!hitBreakpointNumbers.IsEmpty()) { | 615 if (!hitBreakpointNumbers.IsEmpty()) { |
| 610 breakpointIds.reserve(hitBreakpointNumbers->Length()); | 616 breakpointIds.reserve(hitBreakpointNumbers->Length()); |
| 611 for (uint32_t i = 0; i < hitBreakpointNumbers->Length(); i++) { | 617 for (uint32_t i = 0; i < hitBreakpointNumbers->Length(); i++) { |
| 612 v8::Local<v8::Value> hitBreakpointNumber = | 618 v8::Local<v8::Value> hitBreakpointNumber = |
| 613 hitBreakpointNumbers->Get(debuggerContext(), i).ToLocalChecked(); | 619 hitBreakpointNumbers->Get(debuggerContext(), i).ToLocalChecked(); |
| 614 DCHECK(hitBreakpointNumber->IsInt32()); | 620 DCHECK(hitBreakpointNumber->IsInt32()); |
| 615 breakpointIds.push_back(String16::fromInteger( | 621 breakpointIds.push_back(String16::fromInteger( |
| 616 hitBreakpointNumber->Int32Value(debuggerContext()).FromJust())); | 622 hitBreakpointNumber->Int32Value(debuggerContext()).FromJust())); |
| 617 } | 623 } |
| 618 if (breakpointIds.size() == 1 && | 624 if (breakpointIds.size() == 1 && |
| 619 breakpointIds[0] == m_continueToLocationBreakpointId) { | 625 breakpointIds[0] == m_continueToLocationBreakpointId) { |
| 620 v8::Context::Scope contextScope(pausedContext); | 626 v8::Context::Scope contextScope(pausedContext); |
| 621 if (!shouldContinueToCurrentLocation()) return; | 627 if (!shouldContinueToCurrentLocation()) return; |
| 622 } | 628 } |
| 623 } | 629 } |
| 624 clearContinueToLocation(); | 630 clearContinueToLocation(); |
| 625 | 631 |
| 626 DCHECK(contextGroupId); | 632 DCHECK(contextGroupId); |
| 627 m_pausedContext = pausedContext; | 633 m_pausedContext = pausedContext; |
| 628 m_executionState = executionState; | 634 m_executionState = executionState; |
| 629 m_pausedContextGroupId = contextGroupId; | 635 m_pausedContextGroupId = contextGroupId; |
| 630 session->debuggerAgent()->didPause( | 636 |
| 631 InspectedContext::contextId(pausedContext), exception, breakpointIds, | 637 m_inspector->forEachSession( |
| 632 isPromiseRejection, isUncaught, m_scheduledOOMBreak); | 638 contextGroupId, [&agentCheck, &pausedContext, &exception, &breakpointIds, |
| 639 &isPromiseRejection, &isUncaught, |
| 640 &scheduledOOMBreak](V8InspectorSessionImpl* session) { |
| 641 if (agentCheck(session->debuggerAgent())) { |
| 642 session->debuggerAgent()->didPause( |
| 643 InspectedContext::contextId(pausedContext), exception, |
| 644 breakpointIds, isPromiseRejection, isUncaught, scheduledOOMBreak); |
| 645 } |
| 646 }); |
| 633 { | 647 { |
| 634 v8::Context::Scope scope(pausedContext); | 648 v8::Context::Scope scope(pausedContext); |
| 635 v8::Local<v8::Context> context = m_isolate->GetCurrentContext(); | 649 v8::Local<v8::Context> context = m_isolate->GetCurrentContext(); |
| 636 CHECK(!context.IsEmpty() && | 650 CHECK(!context.IsEmpty() && |
| 637 context != v8::debug::GetDebugContext(m_isolate)); | 651 context != v8::debug::GetDebugContext(m_isolate)); |
| 638 m_inspector->client()->runMessageLoopOnPause(contextGroupId); | 652 m_inspector->client()->runMessageLoopOnPause(contextGroupId); |
| 639 m_pausedContextGroupId = 0; | 653 m_pausedContextGroupId = 0; |
| 640 } | 654 } |
| 641 // The agent may have been removed in the nested loop. | 655 m_inspector->forEachSession(contextGroupId, |
| 642 session = m_inspector->sessionForContextGroup(contextGroupId); | 656 [](V8InspectorSessionImpl* session) { |
| 643 if (session && session->debuggerAgent()->enabled()) | 657 if (session->debuggerAgent()->enabled()) |
| 644 session->debuggerAgent()->didContinue(); | 658 session->debuggerAgent()->didContinue(); |
| 659 }); |
| 660 |
| 645 if (m_scheduledOOMBreak) m_isolate->RestoreOriginalHeapLimit(); | 661 if (m_scheduledOOMBreak) m_isolate->RestoreOriginalHeapLimit(); |
| 646 m_scheduledOOMBreak = false; | 662 m_scheduledOOMBreak = false; |
| 647 m_pausedContext.Clear(); | 663 m_pausedContext.Clear(); |
| 648 m_executionState.Clear(); | 664 m_executionState.Clear(); |
| 649 } | 665 } |
| 650 | 666 |
| 651 void V8Debugger::v8OOMCallback(void* data) { | 667 void V8Debugger::v8OOMCallback(void* data) { |
| 652 V8Debugger* thisPtr = static_cast<V8Debugger*>(data); | 668 V8Debugger* thisPtr = static_cast<V8Debugger*>(data); |
| 653 thisPtr->m_isolate->IncreaseHeapLimitForDebugging(); | 669 thisPtr->m_isolate->IncreaseHeapLimitForDebugging(); |
| 654 thisPtr->m_scheduledOOMBreak = true; | 670 thisPtr->m_scheduledOOMBreak = true; |
| 655 v8::Local<v8::Context> context = thisPtr->m_isolate->GetEnteredContext(); | 671 v8::Local<v8::Context> context = thisPtr->m_isolate->GetEnteredContext(); |
| 656 DCHECK(!context.IsEmpty()); | 672 DCHECK(!context.IsEmpty()); |
| 657 thisPtr->setPauseOnNextStatement( | 673 thisPtr->setPauseOnNextStatement( |
| 658 true, thisPtr->m_inspector->contextGroupId(context)); | 674 true, thisPtr->m_inspector->contextGroupId(context)); |
| 659 } | 675 } |
| 660 | 676 |
| 661 void V8Debugger::ScriptCompiled(v8::Local<v8::debug::Script> script, | 677 void V8Debugger::ScriptCompiled(v8::Local<v8::debug::Script> script, |
| 662 bool has_compile_error) { | 678 bool has_compile_error) { |
| 663 int contextId; | 679 int contextId; |
| 664 if (!script->ContextId().To(&contextId)) return; | 680 if (!script->ContextId().To(&contextId)) return; |
| 665 V8InspectorSessionImpl* session = m_inspector->sessionForContextGroup( | |
| 666 m_inspector->contextGroupId(contextId)); | |
| 667 if (!session || !session->debuggerAgent()->enabled()) return; | |
| 668 if (script->IsWasm()) { | 681 if (script->IsWasm()) { |
| 669 m_wasmTranslation.AddScript(script.As<v8::debug::WasmScript>(), | 682 WasmTranslation* wasmTranslation = &m_wasmTranslation; |
| 670 session->debuggerAgent()); | 683 m_inspector->forEachSession( |
| 684 m_inspector->contextGroupId(contextId), |
| 685 [&script, &wasmTranslation](V8InspectorSessionImpl* session) { |
| 686 if (!session->debuggerAgent()->enabled()) return; |
| 687 wasmTranslation->AddScript(script.As<v8::debug::WasmScript>(), |
| 688 session->debuggerAgent()); |
| 689 }); |
| 671 } else if (m_ignoreScriptParsedEventsCounter == 0) { | 690 } else if (m_ignoreScriptParsedEventsCounter == 0) { |
| 672 session->debuggerAgent()->didParseSource( | 691 v8::Isolate* isolate = m_isolate; |
| 673 V8DebuggerScript::Create(m_isolate, script, inLiveEditScope), | 692 m_inspector->forEachSession( |
| 674 !has_compile_error); | 693 m_inspector->contextGroupId(contextId), |
| 694 [&isolate, &script, |
| 695 &has_compile_error](V8InspectorSessionImpl* session) { |
| 696 if (!session->debuggerAgent()->enabled()) return; |
| 697 session->debuggerAgent()->didParseSource( |
| 698 V8DebuggerScript::Create(isolate, script, inLiveEditScope), |
| 699 !has_compile_error); |
| 700 }); |
| 675 } | 701 } |
| 676 } | 702 } |
| 677 | 703 |
| 678 void V8Debugger::BreakProgramRequested(v8::Local<v8::Context> pausedContext, | 704 void V8Debugger::BreakProgramRequested(v8::Local<v8::Context> pausedContext, |
| 679 v8::Local<v8::Object> execState, | 705 v8::Local<v8::Object> execState, |
| 680 v8::Local<v8::Value> breakPointsHit) { | 706 v8::Local<v8::Value> breakPointsHit) { |
| 681 v8::Local<v8::Value> argv[] = {breakPointsHit}; | 707 v8::Local<v8::Value> argv[] = {breakPointsHit}; |
| 682 v8::Local<v8::Value> hitBreakpoints; | 708 v8::Local<v8::Value> hitBreakpoints; |
| 683 if (!callDebuggerMethod("getBreakpointNumbers", 1, argv, true) | 709 if (!callDebuggerMethod("getBreakpointNumbers", 1, argv, true) |
| 684 .ToLocal(&hitBreakpoints)) { | 710 .ToLocal(&hitBreakpoints)) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 697 bool isPromiseRejection = promise->IsPromise(); | 723 bool isPromiseRejection = promise->IsPromise(); |
| 698 handleProgramBreak(pausedContext, execState, exception, | 724 handleProgramBreak(pausedContext, execState, exception, |
| 699 v8::Local<v8::Array>(), isPromiseRejection, isUncaught); | 725 v8::Local<v8::Array>(), isPromiseRejection, isUncaught); |
| 700 } | 726 } |
| 701 | 727 |
| 702 bool V8Debugger::IsFunctionBlackboxed(v8::Local<v8::debug::Script> script, | 728 bool V8Debugger::IsFunctionBlackboxed(v8::Local<v8::debug::Script> script, |
| 703 const v8::debug::Location& start, | 729 const v8::debug::Location& start, |
| 704 const v8::debug::Location& end) { | 730 const v8::debug::Location& end) { |
| 705 int contextId; | 731 int contextId; |
| 706 if (!script->ContextId().To(&contextId)) return false; | 732 if (!script->ContextId().To(&contextId)) return false; |
| 707 V8InspectorSessionImpl* session = m_inspector->sessionForContextGroup( | 733 bool hasAgents = false; |
| 708 m_inspector->contextGroupId(contextId)); | 734 bool allBlackboxed = true; |
| 709 if (!session || !session->debuggerAgent()->enabled()) return false; | 735 String16 scriptId = String16::fromInteger(script->Id()); |
| 710 return session->debuggerAgent()->isFunctionBlackboxed( | 736 m_inspector->forEachSession( |
| 711 String16::fromInteger(script->Id()), start, end); | 737 m_inspector->contextGroupId(contextId), |
| 738 [&hasAgents, &allBlackboxed, &scriptId, &start, |
| 739 &end](V8InspectorSessionImpl* session) { |
| 740 V8DebuggerAgentImpl* agent = session->debuggerAgent(); |
| 741 if (!agent->enabled()) return; |
| 742 hasAgents = true; |
| 743 allBlackboxed &= agent->isFunctionBlackboxed(scriptId, start, end); |
| 744 }); |
| 745 return hasAgents && allBlackboxed; |
| 712 } | 746 } |
| 713 | 747 |
| 714 void V8Debugger::PromiseEventOccurred(v8::debug::PromiseDebugActionType type, | 748 void V8Debugger::PromiseEventOccurred(v8::debug::PromiseDebugActionType type, |
| 715 int id, int parentId, | 749 int id, int parentId, |
| 716 bool createdByUser) { | 750 bool createdByUser) { |
| 717 // Async task events from Promises are given misaligned pointers to prevent | 751 // Async task events from Promises are given misaligned pointers to prevent |
| 718 // from overlapping with other Blink task identifiers. | 752 // from overlapping with other Blink task identifiers. |
| 719 void* task = reinterpret_cast<void*>(id * 2 + 1); | 753 void* task = reinterpret_cast<void*>(id * 2 + 1); |
| 720 void* parentTask = | 754 void* parentTask = |
| 721 parentId ? reinterpret_cast<void*>(parentId * 2 + 1) : nullptr; | 755 parentId ? reinterpret_cast<void*>(parentId * 2 + 1) : nullptr; |
| (...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1077 | 1111 |
| 1078 std::unique_ptr<V8StackTraceImpl> V8Debugger::captureStackTrace( | 1112 std::unique_ptr<V8StackTraceImpl> V8Debugger::captureStackTrace( |
| 1079 bool fullStack) { | 1113 bool fullStack) { |
| 1080 if (!m_isolate->InContext()) return nullptr; | 1114 if (!m_isolate->InContext()) return nullptr; |
| 1081 | 1115 |
| 1082 v8::HandleScope handles(m_isolate); | 1116 v8::HandleScope handles(m_isolate); |
| 1083 int contextGroupId = currentContextGroupId(); | 1117 int contextGroupId = currentContextGroupId(); |
| 1084 if (!contextGroupId) return nullptr; | 1118 if (!contextGroupId) return nullptr; |
| 1085 | 1119 |
| 1086 int stackSize = 1; | 1120 int stackSize = 1; |
| 1087 V8InspectorSessionImpl* session = | 1121 if (fullStack) { |
| 1088 m_inspector->sessionForContextGroup(contextGroupId); | |
| 1089 if (fullStack || (session && session->runtimeAgent()->enabled())) { | |
| 1090 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; | 1122 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; |
| 1123 } else { |
| 1124 m_inspector->forEachSession( |
| 1125 contextGroupId, [&stackSize](V8InspectorSessionImpl* session) { |
| 1126 if (session->runtimeAgent()->enabled()) |
| 1127 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; |
| 1128 }); |
| 1091 } | 1129 } |
| 1092 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); | 1130 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); |
| 1093 } | 1131 } |
| 1094 | 1132 |
| 1095 int V8Debugger::currentContextGroupId() { | 1133 int V8Debugger::currentContextGroupId() { |
| 1096 if (!m_isolate->InContext()) return 0; | 1134 if (!m_isolate->InContext()) return 0; |
| 1097 return m_inspector->contextGroupId(m_isolate->GetCurrentContext()); | 1135 return m_inspector->contextGroupId(m_isolate->GetCurrentContext()); |
| 1098 } | 1136 } |
| 1099 | 1137 |
| 1100 void V8Debugger::collectOldAsyncStacksIfNeeded() { | 1138 void V8Debugger::collectOldAsyncStacksIfNeeded() { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1155 fprintf(stdout, "Async stacks count: %d\n", m_asyncStacksCount); | 1193 fprintf(stdout, "Async stacks count: %d\n", m_asyncStacksCount); |
| 1156 fprintf(stdout, "Scheduled async tasks: %zu\n", m_asyncTaskStacks.size()); | 1194 fprintf(stdout, "Scheduled async tasks: %zu\n", m_asyncTaskStacks.size()); |
| 1157 fprintf(stdout, "Created async tasks: %zu\n", | 1195 fprintf(stdout, "Created async tasks: %zu\n", |
| 1158 m_asyncTaskCreationStacks.size()); | 1196 m_asyncTaskCreationStacks.size()); |
| 1159 fprintf(stdout, "Async tasks with parent: %zu\n", m_parentTask.size()); | 1197 fprintf(stdout, "Async tasks with parent: %zu\n", m_parentTask.size()); |
| 1160 fprintf(stdout, "Recurring async tasks: %zu\n", m_recurringTasks.size()); | 1198 fprintf(stdout, "Recurring async tasks: %zu\n", m_recurringTasks.size()); |
| 1161 fprintf(stdout, "\n"); | 1199 fprintf(stdout, "\n"); |
| 1162 } | 1200 } |
| 1163 | 1201 |
| 1164 } // namespace v8_inspector | 1202 } // namespace v8_inspector |
| OLD | NEW |