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-inspector-session-impl.h" |
14 #include "src/inspector/v8-internal-value-type.h" | 15 #include "src/inspector/v8-internal-value-type.h" |
| 16 #include "src/inspector/v8-runtime-agent-impl.h" |
15 #include "src/inspector/v8-stack-trace-impl.h" | 17 #include "src/inspector/v8-stack-trace-impl.h" |
16 #include "src/inspector/v8-value-copier.h" | 18 #include "src/inspector/v8-value-copier.h" |
17 | 19 |
18 #include "include/v8-util.h" | 20 #include "include/v8-util.h" |
19 | 21 |
20 namespace v8_inspector { | 22 namespace v8_inspector { |
21 | 23 |
22 namespace { | 24 namespace { |
23 | 25 |
24 static const int kMaxAsyncTaskStacks = 128 * 1024; | 26 static const int kMaxAsyncTaskStacks = 128 * 1024; |
25 | 27 |
26 inline v8::Local<v8::Boolean> v8Boolean(bool value, v8::Isolate* isolate) { | 28 inline v8::Local<v8::Boolean> v8Boolean(bool value, v8::Isolate* isolate) { |
27 return value ? v8::True(isolate) : v8::False(isolate); | 29 return value ? v8::True(isolate) : v8::False(isolate); |
28 } | 30 } |
29 | 31 |
30 V8DebuggerAgentImpl* agentForScript(V8InspectorImpl* inspector, | |
31 v8::Local<v8::debug::Script> script) { | |
32 int contextId; | |
33 if (!script->ContextId().To(&contextId)) return nullptr; | |
34 int contextGroupId = inspector->contextGroupId(contextId); | |
35 if (!contextGroupId) return nullptr; | |
36 return inspector->enabledDebuggerAgentForGroup(contextGroupId); | |
37 } | |
38 | |
39 v8::MaybeLocal<v8::Array> collectionsEntries(v8::Local<v8::Context> context, | 32 v8::MaybeLocal<v8::Array> collectionsEntries(v8::Local<v8::Context> context, |
40 v8::Local<v8::Value> value) { | 33 v8::Local<v8::Value> value) { |
41 v8::Isolate* isolate = context->GetIsolate(); | 34 v8::Isolate* isolate = context->GetIsolate(); |
42 v8::Local<v8::Array> entries; | 35 v8::Local<v8::Array> entries; |
43 bool isKeyValue = false; | 36 bool isKeyValue = false; |
44 if (!v8::debug::EntriesPreview(isolate, value, &isKeyValue).ToLocal(&entries)) | 37 if (!v8::debug::EntriesPreview(isolate, value, &isKeyValue).ToLocal(&entries)) |
45 return v8::MaybeLocal<v8::Array>(); | 38 return v8::MaybeLocal<v8::Array>(); |
46 | 39 |
47 v8::Local<v8::Array> wrappedEntries = v8::Array::New(isolate); | 40 v8::Local<v8::Array> wrappedEntries = v8::Array::New(isolate); |
48 CHECK(!isKeyValue || wrappedEntries->Length() % 2 == 0); | 41 CHECK(!isKeyValue || wrappedEntries->Length() % 2 == 0); |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 return !v8::debug::AllFramesOnStackAreBlackboxed(m_isolate); | 347 return !v8::debug::AllFramesOnStackAreBlackboxed(m_isolate); |
355 } | 348 } |
356 | 349 |
357 bool V8Debugger::breakProgram(int targetContextGroupId) { | 350 bool V8Debugger::breakProgram(int targetContextGroupId) { |
358 // Don't allow nested breaks. | 351 // Don't allow nested breaks. |
359 if (isPaused()) return true; | 352 if (isPaused()) return true; |
360 if (!canBreakProgram()) return true; | 353 if (!canBreakProgram()) return true; |
361 DCHECK(targetContextGroupId); | 354 DCHECK(targetContextGroupId); |
362 m_targetContextGroupId = targetContextGroupId; | 355 m_targetContextGroupId = targetContextGroupId; |
363 v8::debug::BreakRightNow(m_isolate); | 356 v8::debug::BreakRightNow(m_isolate); |
364 return m_inspector->enabledDebuggerAgentForGroup(targetContextGroupId); | 357 V8InspectorSessionImpl* session = |
| 358 m_inspector->sessionForContextGroup(targetContextGroupId); |
| 359 return session && session->debuggerAgent()->enabled(); |
365 } | 360 } |
366 | 361 |
367 void V8Debugger::continueProgram(int targetContextGroupId) { | 362 void V8Debugger::continueProgram(int targetContextGroupId) { |
368 if (m_pausedContextGroupId != targetContextGroupId) return; | 363 if (m_pausedContextGroupId != targetContextGroupId) return; |
369 if (isPaused()) m_inspector->client()->quitMessageLoopOnPause(); | 364 if (isPaused()) m_inspector->client()->quitMessageLoopOnPause(); |
370 m_pausedContext.Clear(); | 365 m_pausedContext.Clear(); |
371 m_executionState.Clear(); | 366 m_executionState.Clear(); |
372 } | 367 } |
373 | 368 |
374 void V8Debugger::stepIntoStatement(int targetContextGroupId) { | 369 void V8Debugger::stepIntoStatement(int targetContextGroupId) { |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
598 v8::debug::PrepareStep(m_isolate, v8::debug::StepOut); | 593 v8::debug::PrepareStep(m_isolate, v8::debug::StepOut); |
599 return; | 594 return; |
600 } | 595 } |
601 m_targetContextGroupId = 0; | 596 m_targetContextGroupId = 0; |
602 if (m_stepIntoAsyncCallback) { | 597 if (m_stepIntoAsyncCallback) { |
603 m_stepIntoAsyncCallback->sendFailure( | 598 m_stepIntoAsyncCallback->sendFailure( |
604 Response::Error("No async tasks were scheduled before pause.")); | 599 Response::Error("No async tasks were scheduled before pause.")); |
605 m_stepIntoAsyncCallback.reset(); | 600 m_stepIntoAsyncCallback.reset(); |
606 } | 601 } |
607 m_breakRequested = false; | 602 m_breakRequested = false; |
608 V8DebuggerAgentImpl* agent = m_inspector->enabledDebuggerAgentForGroup( | 603 V8InspectorSessionImpl* session = |
609 m_inspector->contextGroupId(pausedContext)); | 604 m_inspector->sessionForContextGroup(contextGroupId); |
610 if (!agent || (agent->skipAllPauses() && !m_scheduledOOMBreak)) return; | 605 if (!session || !session->debuggerAgent()->enabled()) return; |
| 606 if (!m_scheduledOOMBreak && session->debuggerAgent()->skipAllPauses()) return; |
611 | 607 |
612 std::vector<String16> breakpointIds; | 608 std::vector<String16> breakpointIds; |
613 if (!hitBreakpointNumbers.IsEmpty()) { | 609 if (!hitBreakpointNumbers.IsEmpty()) { |
614 breakpointIds.reserve(hitBreakpointNumbers->Length()); | 610 breakpointIds.reserve(hitBreakpointNumbers->Length()); |
615 for (uint32_t i = 0; i < hitBreakpointNumbers->Length(); i++) { | 611 for (uint32_t i = 0; i < hitBreakpointNumbers->Length(); i++) { |
616 v8::Local<v8::Value> hitBreakpointNumber = | 612 v8::Local<v8::Value> hitBreakpointNumber = |
617 hitBreakpointNumbers->Get(debuggerContext(), i).ToLocalChecked(); | 613 hitBreakpointNumbers->Get(debuggerContext(), i).ToLocalChecked(); |
618 DCHECK(hitBreakpointNumber->IsInt32()); | 614 DCHECK(hitBreakpointNumber->IsInt32()); |
619 breakpointIds.push_back(String16::fromInteger( | 615 breakpointIds.push_back(String16::fromInteger( |
620 hitBreakpointNumber->Int32Value(debuggerContext()).FromJust())); | 616 hitBreakpointNumber->Int32Value(debuggerContext()).FromJust())); |
621 } | 617 } |
622 if (breakpointIds.size() == 1 && | 618 if (breakpointIds.size() == 1 && |
623 breakpointIds[0] == m_continueToLocationBreakpointId) { | 619 breakpointIds[0] == m_continueToLocationBreakpointId) { |
624 v8::Context::Scope contextScope(pausedContext); | 620 v8::Context::Scope contextScope(pausedContext); |
625 if (!shouldContinueToCurrentLocation()) return; | 621 if (!shouldContinueToCurrentLocation()) return; |
626 } | 622 } |
627 } | 623 } |
628 clearContinueToLocation(); | 624 clearContinueToLocation(); |
629 | 625 |
| 626 DCHECK(contextGroupId); |
630 m_pausedContext = pausedContext; | 627 m_pausedContext = pausedContext; |
631 m_executionState = executionState; | 628 m_executionState = executionState; |
632 m_pausedContextGroupId = contextGroupId; | 629 m_pausedContextGroupId = contextGroupId; |
633 agent->didPause(InspectedContext::contextId(pausedContext), exception, | 630 session->debuggerAgent()->didPause( |
634 breakpointIds, isPromiseRejection, isUncaught, | 631 InspectedContext::contextId(pausedContext), exception, breakpointIds, |
635 m_scheduledOOMBreak); | 632 isPromiseRejection, isUncaught, m_scheduledOOMBreak); |
636 int groupId = m_inspector->contextGroupId(pausedContext); | |
637 DCHECK(groupId); | |
638 { | 633 { |
639 v8::Context::Scope scope(pausedContext); | 634 v8::Context::Scope scope(pausedContext); |
640 v8::Local<v8::Context> context = m_isolate->GetCurrentContext(); | 635 v8::Local<v8::Context> context = m_isolate->GetCurrentContext(); |
641 CHECK(!context.IsEmpty() && | 636 CHECK(!context.IsEmpty() && |
642 context != v8::debug::GetDebugContext(m_isolate)); | 637 context != v8::debug::GetDebugContext(m_isolate)); |
643 m_inspector->client()->runMessageLoopOnPause(groupId); | 638 m_inspector->client()->runMessageLoopOnPause(contextGroupId); |
644 m_pausedContextGroupId = 0; | 639 m_pausedContextGroupId = 0; |
645 } | 640 } |
646 // The agent may have been removed in the nested loop. | 641 // The agent may have been removed in the nested loop. |
647 agent = m_inspector->enabledDebuggerAgentForGroup(groupId); | 642 session = m_inspector->sessionForContextGroup(contextGroupId); |
648 if (agent) agent->didContinue(); | 643 if (session && session->debuggerAgent()->enabled()) |
| 644 session->debuggerAgent()->didContinue(); |
649 if (m_scheduledOOMBreak) m_isolate->RestoreOriginalHeapLimit(); | 645 if (m_scheduledOOMBreak) m_isolate->RestoreOriginalHeapLimit(); |
650 m_scheduledOOMBreak = false; | 646 m_scheduledOOMBreak = false; |
651 m_pausedContext.Clear(); | 647 m_pausedContext.Clear(); |
652 m_executionState.Clear(); | 648 m_executionState.Clear(); |
653 } | 649 } |
654 | 650 |
655 void V8Debugger::v8OOMCallback(void* data) { | 651 void V8Debugger::v8OOMCallback(void* data) { |
656 V8Debugger* thisPtr = static_cast<V8Debugger*>(data); | 652 V8Debugger* thisPtr = static_cast<V8Debugger*>(data); |
657 thisPtr->m_isolate->IncreaseHeapLimitForDebugging(); | 653 thisPtr->m_isolate->IncreaseHeapLimitForDebugging(); |
658 thisPtr->m_scheduledOOMBreak = true; | 654 thisPtr->m_scheduledOOMBreak = true; |
659 v8::Local<v8::Context> context = thisPtr->m_isolate->GetEnteredContext(); | 655 v8::Local<v8::Context> context = thisPtr->m_isolate->GetEnteredContext(); |
660 DCHECK(!context.IsEmpty()); | 656 DCHECK(!context.IsEmpty()); |
661 thisPtr->setPauseOnNextStatement( | 657 thisPtr->setPauseOnNextStatement( |
662 true, thisPtr->m_inspector->contextGroupId(context)); | 658 true, thisPtr->m_inspector->contextGroupId(context)); |
663 } | 659 } |
664 | 660 |
665 void V8Debugger::ScriptCompiled(v8::Local<v8::debug::Script> script, | 661 void V8Debugger::ScriptCompiled(v8::Local<v8::debug::Script> script, |
666 bool has_compile_error) { | 662 bool has_compile_error) { |
667 V8DebuggerAgentImpl* agent = agentForScript(m_inspector, script); | 663 int contextId; |
668 if (!agent) return; | 664 if (!script->ContextId().To(&contextId)) return; |
| 665 V8InspectorSessionImpl* session = m_inspector->sessionForContextGroup( |
| 666 m_inspector->contextGroupId(contextId)); |
| 667 if (!session || !session->debuggerAgent()->enabled()) return; |
669 if (script->IsWasm()) { | 668 if (script->IsWasm()) { |
670 m_wasmTranslation.AddScript(script.As<v8::debug::WasmScript>(), agent); | 669 m_wasmTranslation.AddScript(script.As<v8::debug::WasmScript>(), |
| 670 session->debuggerAgent()); |
671 } else if (m_ignoreScriptParsedEventsCounter == 0) { | 671 } else if (m_ignoreScriptParsedEventsCounter == 0) { |
672 agent->didParseSource( | 672 session->debuggerAgent()->didParseSource( |
673 V8DebuggerScript::Create(m_isolate, script, inLiveEditScope), | 673 V8DebuggerScript::Create(m_isolate, script, inLiveEditScope), |
674 !has_compile_error); | 674 !has_compile_error); |
675 } | 675 } |
676 } | 676 } |
677 | 677 |
678 void V8Debugger::BreakProgramRequested(v8::Local<v8::Context> pausedContext, | 678 void V8Debugger::BreakProgramRequested(v8::Local<v8::Context> pausedContext, |
679 v8::Local<v8::Object> execState, | 679 v8::Local<v8::Object> execState, |
680 v8::Local<v8::Value> breakPointsHit) { | 680 v8::Local<v8::Value> breakPointsHit) { |
681 v8::Local<v8::Value> argv[] = {breakPointsHit}; | 681 v8::Local<v8::Value> argv[] = {breakPointsHit}; |
682 v8::Local<v8::Value> hitBreakpoints; | 682 v8::Local<v8::Value> hitBreakpoints; |
(...skipping 12 matching lines...) Expand all Loading... |
695 v8::Local<v8::Value> promise, | 695 v8::Local<v8::Value> promise, |
696 bool isUncaught) { | 696 bool isUncaught) { |
697 bool isPromiseRejection = promise->IsPromise(); | 697 bool isPromiseRejection = promise->IsPromise(); |
698 handleProgramBreak(pausedContext, execState, exception, | 698 handleProgramBreak(pausedContext, execState, exception, |
699 v8::Local<v8::Array>(), isPromiseRejection, isUncaught); | 699 v8::Local<v8::Array>(), isPromiseRejection, isUncaught); |
700 } | 700 } |
701 | 701 |
702 bool V8Debugger::IsFunctionBlackboxed(v8::Local<v8::debug::Script> script, | 702 bool V8Debugger::IsFunctionBlackboxed(v8::Local<v8::debug::Script> script, |
703 const v8::debug::Location& start, | 703 const v8::debug::Location& start, |
704 const v8::debug::Location& end) { | 704 const v8::debug::Location& end) { |
705 V8DebuggerAgentImpl* agent = agentForScript(m_inspector, script); | 705 int contextId; |
706 if (!agent) return false; | 706 if (!script->ContextId().To(&contextId)) return false; |
707 return agent->isFunctionBlackboxed(String16::fromInteger(script->Id()), start, | 707 V8InspectorSessionImpl* session = m_inspector->sessionForContextGroup( |
708 end); | 708 m_inspector->contextGroupId(contextId)); |
| 709 if (!session || !session->debuggerAgent()->enabled()) return false; |
| 710 return session->debuggerAgent()->isFunctionBlackboxed( |
| 711 String16::fromInteger(script->Id()), start, end); |
709 } | 712 } |
710 | 713 |
711 void V8Debugger::PromiseEventOccurred(v8::debug::PromiseDebugActionType type, | 714 void V8Debugger::PromiseEventOccurred(v8::debug::PromiseDebugActionType type, |
712 int id, int parentId, | 715 int id, int parentId, |
713 bool createdByUser) { | 716 bool createdByUser) { |
714 // Async task events from Promises are given misaligned pointers to prevent | 717 // Async task events from Promises are given misaligned pointers to prevent |
715 // from overlapping with other Blink task identifiers. | 718 // from overlapping with other Blink task identifiers. |
716 void* task = reinterpret_cast<void*>(id * 2 + 1); | 719 void* task = reinterpret_cast<void*>(id * 2 + 1); |
717 void* parentTask = | 720 void* parentTask = |
718 parentId ? reinterpret_cast<void*>(parentId * 2 + 1) : nullptr; | 721 parentId ? reinterpret_cast<void*>(parentId * 2 + 1) : nullptr; |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1074 | 1077 |
1075 std::unique_ptr<V8StackTraceImpl> V8Debugger::captureStackTrace( | 1078 std::unique_ptr<V8StackTraceImpl> V8Debugger::captureStackTrace( |
1076 bool fullStack) { | 1079 bool fullStack) { |
1077 if (!m_isolate->InContext()) return nullptr; | 1080 if (!m_isolate->InContext()) return nullptr; |
1078 | 1081 |
1079 v8::HandleScope handles(m_isolate); | 1082 v8::HandleScope handles(m_isolate); |
1080 int contextGroupId = currentContextGroupId(); | 1083 int contextGroupId = currentContextGroupId(); |
1081 if (!contextGroupId) return nullptr; | 1084 if (!contextGroupId) return nullptr; |
1082 | 1085 |
1083 int stackSize = 1; | 1086 int stackSize = 1; |
1084 if (fullStack || m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) { | 1087 V8InspectorSessionImpl* session = |
| 1088 m_inspector->sessionForContextGroup(contextGroupId); |
| 1089 if (fullStack || (session && session->runtimeAgent()->enabled())) { |
1085 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; | 1090 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; |
1086 } | 1091 } |
1087 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); | 1092 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); |
1088 } | 1093 } |
1089 | 1094 |
1090 int V8Debugger::currentContextGroupId() { | 1095 int V8Debugger::currentContextGroupId() { |
1091 if (!m_isolate->InContext()) return 0; | 1096 if (!m_isolate->InContext()) return 0; |
1092 return m_inspector->contextGroupId(m_isolate->GetCurrentContext()); | 1097 return m_inspector->contextGroupId(m_isolate->GetCurrentContext()); |
1093 } | 1098 } |
1094 | 1099 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1150 fprintf(stdout, "Async stacks count: %d\n", m_asyncStacksCount); | 1155 fprintf(stdout, "Async stacks count: %d\n", m_asyncStacksCount); |
1151 fprintf(stdout, "Scheduled async tasks: %zu\n", m_asyncTaskStacks.size()); | 1156 fprintf(stdout, "Scheduled async tasks: %zu\n", m_asyncTaskStacks.size()); |
1152 fprintf(stdout, "Created async tasks: %zu\n", | 1157 fprintf(stdout, "Created async tasks: %zu\n", |
1153 m_asyncTaskCreationStacks.size()); | 1158 m_asyncTaskCreationStacks.size()); |
1154 fprintf(stdout, "Async tasks with parent: %zu\n", m_parentTask.size()); | 1159 fprintf(stdout, "Async tasks with parent: %zu\n", m_parentTask.size()); |
1155 fprintf(stdout, "Recurring async tasks: %zu\n", m_recurringTasks.size()); | 1160 fprintf(stdout, "Recurring async tasks: %zu\n", m_recurringTasks.size()); |
1156 fprintf(stdout, "\n"); | 1161 fprintf(stdout, "\n"); |
1157 } | 1162 } |
1158 | 1163 |
1159 } // namespace v8_inspector | 1164 } // namespace v8_inspector |
OLD | NEW |