Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(608)

Side by Side Diff: src/inspector/v8-debugger.cc

Issue 2655253004: [inspector] introduced stepIntoAsync for chained callbacks (Closed)
Patch Set: fixed async/await and added tests Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/inspector/v8-debugger.h ('k') | src/inspector/v8-debugger-agent-impl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 compileDebuggerScript(); 187 compileDebuggerScript();
188 } 188 }
189 189
190 void V8Debugger::disable() { 190 void V8Debugger::disable() {
191 if (--m_enableCount) return; 191 if (--m_enableCount) return;
192 DCHECK(enabled()); 192 DCHECK(enabled());
193 clearBreakpoints(); 193 clearBreakpoints();
194 m_debuggerScript.Reset(); 194 m_debuggerScript.Reset();
195 m_debuggerContext.Reset(); 195 m_debuggerContext.Reset();
196 allAsyncTasksCanceled(); 196 allAsyncTasksCanceled();
197 m_tasksWithScheduledBreak.clear();
197 m_wasmTranslation.Clear(); 198 m_wasmTranslation.Clear();
198 v8::debug::SetDebugDelegate(m_isolate, nullptr); 199 v8::debug::SetDebugDelegate(m_isolate, nullptr);
199 v8::debug::SetOutOfMemoryCallback(m_isolate, nullptr, nullptr); 200 v8::debug::SetOutOfMemoryCallback(m_isolate, nullptr, nullptr);
200 m_isolate->RestoreOriginalHeapLimit(); 201 m_isolate->RestoreOriginalHeapLimit();
201 } 202 }
202 203
203 bool V8Debugger::enabled() const { return !m_debuggerScript.IsEmpty(); } 204 bool V8Debugger::enabled() const { return !m_debuggerScript.IsEmpty(); }
204 205
205 void V8Debugger::getCompiledScripts( 206 void V8Debugger::getCompiledScripts(
206 int contextGroupId, 207 int contextGroupId,
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 v8::Local<v8::Function> breakFunction; 350 v8::Local<v8::Function> breakFunction;
350 if (!v8::Function::New(m_isolate->GetCurrentContext(), 351 if (!v8::Function::New(m_isolate->GetCurrentContext(),
351 &V8Debugger::breakProgramCallback, 352 &V8Debugger::breakProgramCallback,
352 v8::External::New(m_isolate, this), 0, 353 v8::External::New(m_isolate, this), 0,
353 v8::ConstructorBehavior::kThrow) 354 v8::ConstructorBehavior::kThrow)
354 .ToLocal(&breakFunction)) 355 .ToLocal(&breakFunction))
355 return; 356 return;
356 v8::debug::Call(debuggerContext(), breakFunction).ToLocalChecked(); 357 v8::debug::Call(debuggerContext(), breakFunction).ToLocalChecked();
357 } 358 }
358 359
359 void V8Debugger::continueProgram() { 360 void V8Debugger::continueProgramImpl() {
360 if (isPaused()) m_inspector->client()->quitMessageLoopOnPause(); 361 if (!isPaused()) return;
362 m_inspector->client()->quitMessageLoopOnPause();
361 m_pausedContext.Clear(); 363 m_pausedContext.Clear();
362 m_executionState.Clear(); 364 m_executionState.Clear();
363 } 365 }
364 366
367 void V8Debugger::continueProgram() {
368 if (!isPaused()) return;
369 v8::debug::ClearStepping(m_isolate);
370 continueProgramImpl();
371 }
372
365 void V8Debugger::stepIntoStatement() { 373 void V8Debugger::stepIntoStatement() {
366 DCHECK(isPaused()); 374 DCHECK(isPaused());
367 DCHECK(!m_executionState.IsEmpty()); 375 DCHECK(!m_executionState.IsEmpty());
368 v8::debug::PrepareStep(m_isolate, v8::debug::StepIn); 376 v8::debug::PrepareStep(m_isolate, v8::debug::StepIn);
369 continueProgram(); 377 continueProgramImpl();
370 } 378 }
371 379
372 void V8Debugger::stepOverStatement() { 380 void V8Debugger::stepOverStatement() {
373 DCHECK(isPaused()); 381 DCHECK(isPaused());
374 DCHECK(!m_executionState.IsEmpty()); 382 DCHECK(!m_executionState.IsEmpty());
375 v8::debug::PrepareStep(m_isolate, v8::debug::StepNext); 383 v8::debug::PrepareStep(m_isolate, v8::debug::StepNext);
376 continueProgram(); 384 continueProgramImpl();
377 } 385 }
378 386
379 void V8Debugger::stepOutOfFunction() { 387 void V8Debugger::stepOutOfFunction() {
380 DCHECK(isPaused()); 388 DCHECK(isPaused());
381 DCHECK(!m_executionState.IsEmpty()); 389 DCHECK(!m_executionState.IsEmpty());
382 v8::debug::PrepareStep(m_isolate, v8::debug::StepOut); 390 v8::debug::PrepareStep(m_isolate, v8::debug::StepOut);
383 continueProgram(); 391 continueProgramImpl();
392 }
393
394 Response V8Debugger::stepIntoScheduledCallback() {
395 DCHECK(isPaused());
396 DCHECK(!m_executionState.IsEmpty());
397
398 if (!stepIntoScheduledCallbackAvailable()) {
399 return Response::Error("No scheduled callback for stepInto available.");
400 }
401 m_tasksWithScheduledBreak.insert(m_createdPromiseTask);
402 v8::debug::ClearStepping(m_isolate);
403 continueProgramImpl();
404 return Response::OK();
405 }
406
407 bool V8Debugger::stepIntoScheduledCallbackAvailable() {
408 return m_createdPromiseTask;
384 } 409 }
385 410
386 Response V8Debugger::setScriptSource( 411 Response V8Debugger::setScriptSource(
387 const String16& sourceID, v8::Local<v8::String> newSource, bool dryRun, 412 const String16& sourceID, v8::Local<v8::String> newSource, bool dryRun,
388 Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails, 413 Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails,
389 JavaScriptCallFrames* newCallFrames, Maybe<bool>* stackChanged, 414 JavaScriptCallFrames* newCallFrames, Maybe<bool>* stackChanged,
390 bool* compileError) { 415 bool* compileError) {
391 class EnableLiveEditScope { 416 class EnableLiveEditScope {
392 public: 417 public:
393 explicit EnableLiveEditScope(v8::Isolate* isolate) : m_isolate(isolate) { 418 explicit EnableLiveEditScope(v8::Isolate* isolate) : m_isolate(isolate) {
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 643
619 bool V8Debugger::IsFunctionBlackboxed(v8::Local<v8::debug::Script> script, 644 bool V8Debugger::IsFunctionBlackboxed(v8::Local<v8::debug::Script> script,
620 const v8::debug::Location& start, 645 const v8::debug::Location& start,
621 const v8::debug::Location& end) { 646 const v8::debug::Location& end) {
622 V8DebuggerAgentImpl* agent = agentForScript(m_inspector, script); 647 V8DebuggerAgentImpl* agent = agentForScript(m_inspector, script);
623 if (!agent) return false; 648 if (!agent) return false;
624 return agent->isFunctionBlackboxed(String16::fromInteger(script->Id()), start, 649 return agent->isFunctionBlackboxed(String16::fromInteger(script->Id()), start,
625 end); 650 end);
626 } 651 }
627 652
628 void V8Debugger::PromiseEventOccurred(v8::debug::PromiseDebugActionType type, 653 void V8Debugger::PromiseEventOccurred(v8::Local<v8::Context> context,
629 int id, int parentId) { 654 v8::debug::PromiseDebugActionType type,
630 if (!m_maxAsyncCallStackDepth) return; 655 int id, int parentId, bool breakable) {
631 // Async task events from Promises are given misaligned pointers to prevent 656 // Async task events from Promises are given misaligned pointers to prevent
632 // from overlapping with other Blink task identifiers. There is a single 657 // from overlapping with other Blink task identifiers. There is a single
633 // namespace of such ids, managed by src/js/promise.js. 658 // namespace of such ids, managed by src/js/promise.js.
634 void* ptr = reinterpret_cast<void*>(id * 2 + 1); 659 void* ptr = reinterpret_cast<void*>(id * 2 + 1);
660 void* parentPtr =
661 parentId ? reinterpret_cast<void*>(parentId * 2 + 1) : nullptr;
662 if ((breakable && type == v8::debug::kDebugPromiseCreated) ||
663 type == v8::debug::kDebugWillHandle ||
664 type == v8::debug::kDebugDidHandle ||
665 type == v8::debug::kDebugPromiseCollected) {
666 steppingOnPromiseEvent(context, type, ptr, parentPtr);
667 }
668 if (!m_maxAsyncCallStackDepth) return;
635 switch (type) { 669 switch (type) {
636 case v8::debug::kDebugPromiseCreated: 670 case v8::debug::kDebugPromiseCreated:
637 asyncTaskCreated( 671 asyncTaskCreated(ptr, parentPtr);
638 ptr, parentId ? reinterpret_cast<void*>(parentId * 2 + 1) : nullptr);
639 break; 672 break;
640 case v8::debug::kDebugEnqueueAsyncFunction: 673 case v8::debug::kDebugEnqueueAsyncFunction:
641 asyncTaskScheduled("async function", ptr, true); 674 asyncTaskScheduled("async function", ptr, true);
642 break; 675 break;
643 case v8::debug::kDebugEnqueuePromiseResolve: 676 case v8::debug::kDebugEnqueuePromiseResolve:
644 asyncTaskScheduled("Promise.resolve", ptr, true); 677 asyncTaskScheduled("Promise.resolve", ptr, true);
645 break; 678 break;
646 case v8::debug::kDebugEnqueuePromiseReject: 679 case v8::debug::kDebugEnqueuePromiseReject:
647 asyncTaskScheduled("Promise.reject", ptr, true); 680 asyncTaskScheduled("Promise.reject", ptr, true);
648 break; 681 break;
649 case v8::debug::kDebugPromiseCollected: 682 case v8::debug::kDebugPromiseCollected:
650 asyncTaskCanceled(ptr); 683 asyncTaskCanceled(ptr);
651 break; 684 break;
652 case v8::debug::kDebugWillHandle: 685 case v8::debug::kDebugWillHandle:
653 asyncTaskStarted(ptr); 686 asyncTaskStarted(ptr);
654 break; 687 break;
655 case v8::debug::kDebugDidHandle: 688 case v8::debug::kDebugDidHandle:
656 asyncTaskFinished(ptr); 689 asyncTaskFinished(ptr);
657 break; 690 break;
658 } 691 }
659 } 692 }
660 693
694 void V8Debugger::steppingOnPromiseEvent(v8::Local<v8::Context> context,
695 v8::debug::PromiseDebugActionType type,
696 void* task, void* parentPtr) {
697 if (type == v8::debug::kDebugPromiseCollected) {
698 m_tasksWithScheduledBreak.erase(task);
699 return;
700 }
701 DCHECK(!context.IsEmpty());
702 v8::Context::Scope contextScope(context);
703 V8DebuggerAgentImpl* agent =
704 m_inspector->enabledDebuggerAgentForGroup(currentContextGroupId());
705 if (!agent) return;
706 if (type == v8::debug::kDebugPromiseCreated) {
707 if (!parentPtr) return;
708 m_createdPromiseTask = task;
709 agent->breakProgramIfSteppingInto(
710 protocol::Debugger::Paused::ReasonEnum::Other, nullptr);
711 m_createdPromiseTask = nullptr;
712 return;
713 }
714 if (m_tasksWithScheduledBreak.find(task) == m_tasksWithScheduledBreak.end()) {
715 return;
716 }
717 if (type == v8::debug::kDebugWillHandle) {
718 agent->schedulePauseOnNextStatement(
719 protocol::Debugger::Paused::ReasonEnum::Other, nullptr);
720 } else {
721 agent->cancelPauseOnNextStatement();
722 }
723 }
724
661 V8StackTraceImpl* V8Debugger::currentAsyncCallChain() { 725 V8StackTraceImpl* V8Debugger::currentAsyncCallChain() {
662 if (!m_currentStacks.size()) return nullptr; 726 if (!m_currentStacks.size()) return nullptr;
663 return m_currentStacks.back().get(); 727 return m_currentStacks.back().get();
664 } 728 }
665 729
666 void V8Debugger::compileDebuggerScript() { 730 void V8Debugger::compileDebuggerScript() {
667 if (!m_debuggerScript.IsEmpty()) { 731 if (!m_debuggerScript.IsEmpty()) {
668 UNREACHABLE(); 732 UNREACHABLE();
669 return; 733 return;
670 } 734 }
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
795 createDataProperty(context, properties, properties->Length(), 859 createDataProperty(context, properties, properties->Length(),
796 toV8StringInternalized(m_isolate, "[[Scopes]]")); 860 toV8StringInternalized(m_isolate, "[[Scopes]]"));
797 createDataProperty(context, properties, properties->Length(), scopes); 861 createDataProperty(context, properties, properties->Length(), scopes);
798 } 862 }
799 } 863 }
800 return properties; 864 return properties;
801 } 865 }
802 866
803 std::unique_ptr<V8StackTraceImpl> V8Debugger::createStackTrace( 867 std::unique_ptr<V8StackTraceImpl> V8Debugger::createStackTrace(
804 v8::Local<v8::StackTrace> stackTrace) { 868 v8::Local<v8::StackTrace> stackTrace) {
805 int contextGroupId = 869 return V8StackTraceImpl::create(this, currentContextGroupId(), stackTrace,
806 m_isolate->InContext()
807 ? m_inspector->contextGroupId(m_isolate->GetCurrentContext())
808 : 0;
809 return V8StackTraceImpl::create(this, contextGroupId, stackTrace,
810 V8StackTraceImpl::maxCallStackSizeToCapture); 870 V8StackTraceImpl::maxCallStackSizeToCapture);
811 } 871 }
812 872
813 void V8Debugger::setAsyncCallStackDepth(V8DebuggerAgentImpl* agent, int depth) { 873 void V8Debugger::setAsyncCallStackDepth(V8DebuggerAgentImpl* agent, int depth) {
814 if (depth <= 0) 874 if (depth <= 0)
815 m_maxAsyncCallStackDepthMap.erase(agent); 875 m_maxAsyncCallStackDepthMap.erase(agent);
816 else 876 else
817 m_maxAsyncCallStackDepthMap[agent] = depth; 877 m_maxAsyncCallStackDepthMap[agent] = depth;
818 878
819 int maxAsyncCallStackDepth = 0; 879 int maxAsyncCallStackDepth = 0;
(...skipping 16 matching lines...) Expand all
836 if (static_cast<int>(m_idToTask.size()) > m_maxAsyncCallStacks) { 896 if (static_cast<int>(m_idToTask.size()) > m_maxAsyncCallStacks) {
837 void* taskToRemove = m_idToTask.begin()->second; 897 void* taskToRemove = m_idToTask.begin()->second;
838 asyncTaskCanceled(taskToRemove); 898 asyncTaskCanceled(taskToRemove);
839 } 899 }
840 } 900 }
841 901
842 void V8Debugger::asyncTaskCreated(void* task, void* parentTask) { 902 void V8Debugger::asyncTaskCreated(void* task, void* parentTask) {
843 if (!m_maxAsyncCallStackDepth) return; 903 if (!m_maxAsyncCallStackDepth) return;
844 if (parentTask) m_parentTask[task] = parentTask; 904 if (parentTask) m_parentTask[task] = parentTask;
845 v8::HandleScope scope(m_isolate); 905 v8::HandleScope scope(m_isolate);
846 // We don't need to pass context group id here because we gets this callback 906 // We don't need to pass context group id here because we get this callback
847 // from V8 for promise events only. 907 // from V8 for promise events only.
848 // Passing one as maxStackSize forces no async chain for the new stack and 908 // Passing one as maxStackSize forces no async chain for the new stack and
849 // allows us to not grow exponentially. 909 // allows us to not grow exponentially.
850 std::unique_ptr<V8StackTraceImpl> creationStack = 910 std::unique_ptr<V8StackTraceImpl> creationStack =
851 V8StackTraceImpl::capture(this, 0, 1, String16()); 911 V8StackTraceImpl::capture(this, 0, 1, String16());
852 if (creationStack && !creationStack->isEmpty()) { 912 if (creationStack && !creationStack->isEmpty()) {
853 m_asyncTaskCreationStacks[task] = std::move(creationStack); 913 m_asyncTaskCreationStacks[task] = std::move(creationStack);
854 registerAsyncTaskIfNeeded(task); 914 registerAsyncTaskIfNeeded(task);
855 } 915 }
856 } 916 }
857 917
858 void V8Debugger::asyncTaskScheduled(const StringView& taskName, void* task, 918 void V8Debugger::asyncTaskScheduled(const StringView& taskName, void* task,
859 bool recurring) { 919 bool recurring) {
860 if (!m_maxAsyncCallStackDepth) return; 920 if (!m_maxAsyncCallStackDepth) return;
861 asyncTaskScheduled(toString16(taskName), task, recurring); 921 asyncTaskScheduled(toString16(taskName), task, recurring);
862 } 922 }
863 923
864 void V8Debugger::asyncTaskScheduled(const String16& taskName, void* task, 924 void V8Debugger::asyncTaskScheduled(const String16& taskName, void* task,
865 bool recurring) { 925 bool recurring) {
866 if (!m_maxAsyncCallStackDepth) return; 926 if (!m_maxAsyncCallStackDepth) return;
867 v8::HandleScope scope(m_isolate); 927 v8::HandleScope scope(m_isolate);
868 int contextGroupId =
869 m_isolate->InContext()
870 ? m_inspector->contextGroupId(m_isolate->GetCurrentContext())
871 : 0;
872 std::unique_ptr<V8StackTraceImpl> chain = V8StackTraceImpl::capture( 928 std::unique_ptr<V8StackTraceImpl> chain = V8StackTraceImpl::capture(
873 this, contextGroupId, V8StackTraceImpl::maxCallStackSizeToCapture, 929 this, currentContextGroupId(),
874 taskName); 930 V8StackTraceImpl::maxCallStackSizeToCapture, taskName);
875 if (chain) { 931 if (chain) {
876 m_asyncTaskStacks[task] = std::move(chain); 932 m_asyncTaskStacks[task] = std::move(chain);
877 if (recurring) m_recurringTasks.insert(task); 933 if (recurring) m_recurringTasks.insert(task);
878 registerAsyncTaskIfNeeded(task); 934 registerAsyncTaskIfNeeded(task);
879 } 935 }
880 } 936 }
881 937
882 void V8Debugger::asyncTaskCanceled(void* task) { 938 void V8Debugger::asyncTaskCanceled(void* task) {
883 if (!m_maxAsyncCallStackDepth) return; 939 if (!m_maxAsyncCallStackDepth) return;
884 m_asyncTaskStacks.erase(task); 940 m_asyncTaskStacks.erase(task);
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
947 void V8Debugger::unmuteScriptParsedEvents() { 1003 void V8Debugger::unmuteScriptParsedEvents() {
948 --m_ignoreScriptParsedEventsCounter; 1004 --m_ignoreScriptParsedEventsCounter;
949 DCHECK_GE(m_ignoreScriptParsedEventsCounter, 0); 1005 DCHECK_GE(m_ignoreScriptParsedEventsCounter, 0);
950 } 1006 }
951 1007
952 std::unique_ptr<V8StackTraceImpl> V8Debugger::captureStackTrace( 1008 std::unique_ptr<V8StackTraceImpl> V8Debugger::captureStackTrace(
953 bool fullStack) { 1009 bool fullStack) {
954 if (!m_isolate->InContext()) return nullptr; 1010 if (!m_isolate->InContext()) return nullptr;
955 1011
956 v8::HandleScope handles(m_isolate); 1012 v8::HandleScope handles(m_isolate);
957 int contextGroupId = 1013 int contextGroupId = currentContextGroupId();
958 m_inspector->contextGroupId(m_isolate->GetCurrentContext());
959 if (!contextGroupId) return nullptr; 1014 if (!contextGroupId) return nullptr;
960 1015
961 size_t stackSize = 1016 size_t stackSize =
962 fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1; 1017 fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1;
963 if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) 1018 if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId))
964 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; 1019 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture;
965 1020
966 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); 1021 return V8StackTraceImpl::capture(this, contextGroupId, stackSize);
967 } 1022 }
968 1023
1024 int V8Debugger::currentContextGroupId() {
1025 if (!m_isolate->InContext()) return 0;
1026 return m_inspector->contextGroupId(m_isolate->GetCurrentContext());
1027 }
1028
969 } // namespace v8_inspector 1029 } // namespace v8_inspector
OLDNEW
« no previous file with comments | « src/inspector/v8-debugger.h ('k') | src/inspector/v8-debugger-agent-impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698