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

Unified 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/inspector/v8-debugger.cc
diff --git a/src/inspector/v8-debugger.cc b/src/inspector/v8-debugger.cc
index 3a2fc89f0039869b49a3c5cef4f4b92eab0017a6..ea0a66ea7d7a31ae3ca8e0b044c69da14bae666e 100644
--- a/src/inspector/v8-debugger.cc
+++ b/src/inspector/v8-debugger.cc
@@ -194,6 +194,7 @@ void V8Debugger::disable() {
m_debuggerScript.Reset();
m_debuggerContext.Reset();
allAsyncTasksCanceled();
+ m_tasksWithScheduledBreak.clear();
m_wasmTranslation.Clear();
v8::debug::SetDebugDelegate(m_isolate, nullptr);
v8::debug::SetOutOfMemoryCallback(m_isolate, nullptr, nullptr);
@@ -356,31 +357,55 @@ void V8Debugger::breakProgram() {
v8::debug::Call(debuggerContext(), breakFunction).ToLocalChecked();
}
-void V8Debugger::continueProgram() {
- if (isPaused()) m_inspector->client()->quitMessageLoopOnPause();
+void V8Debugger::continueProgramImpl() {
+ if (!isPaused()) return;
+ m_inspector->client()->quitMessageLoopOnPause();
m_pausedContext.Clear();
m_executionState.Clear();
}
+void V8Debugger::continueProgram() {
+ if (!isPaused()) return;
+ v8::debug::ClearStepping(m_isolate);
+ continueProgramImpl();
+}
+
void V8Debugger::stepIntoStatement() {
DCHECK(isPaused());
DCHECK(!m_executionState.IsEmpty());
v8::debug::PrepareStep(m_isolate, v8::debug::StepIn);
- continueProgram();
+ continueProgramImpl();
}
void V8Debugger::stepOverStatement() {
DCHECK(isPaused());
DCHECK(!m_executionState.IsEmpty());
v8::debug::PrepareStep(m_isolate, v8::debug::StepNext);
- continueProgram();
+ continueProgramImpl();
}
void V8Debugger::stepOutOfFunction() {
DCHECK(isPaused());
DCHECK(!m_executionState.IsEmpty());
v8::debug::PrepareStep(m_isolate, v8::debug::StepOut);
- continueProgram();
+ continueProgramImpl();
+}
+
+Response V8Debugger::stepIntoScheduledCallback() {
+ DCHECK(isPaused());
+ DCHECK(!m_executionState.IsEmpty());
+
+ if (!stepIntoScheduledCallbackAvailable()) {
+ return Response::Error("No scheduled callback for stepInto available.");
+ }
+ m_tasksWithScheduledBreak.insert(m_createdPromiseTask);
+ v8::debug::ClearStepping(m_isolate);
+ continueProgramImpl();
+ return Response::OK();
+}
+
+bool V8Debugger::stepIntoScheduledCallbackAvailable() {
+ return m_createdPromiseTask;
}
Response V8Debugger::setScriptSource(
@@ -625,17 +650,25 @@ bool V8Debugger::IsFunctionBlackboxed(v8::Local<v8::debug::Script> script,
end);
}
-void V8Debugger::PromiseEventOccurred(v8::debug::PromiseDebugActionType type,
- int id, int parentId) {
- if (!m_maxAsyncCallStackDepth) return;
+void V8Debugger::PromiseEventOccurred(v8::Local<v8::Context> context,
+ v8::debug::PromiseDebugActionType type,
+ int id, int parentId, bool breakable) {
// Async task events from Promises are given misaligned pointers to prevent
// from overlapping with other Blink task identifiers. There is a single
// namespace of such ids, managed by src/js/promise.js.
void* ptr = reinterpret_cast<void*>(id * 2 + 1);
+ void* parentPtr =
+ parentId ? reinterpret_cast<void*>(parentId * 2 + 1) : nullptr;
+ if ((breakable && type == v8::debug::kDebugPromiseCreated) ||
+ type == v8::debug::kDebugWillHandle ||
+ type == v8::debug::kDebugDidHandle ||
+ type == v8::debug::kDebugPromiseCollected) {
+ steppingOnPromiseEvent(context, type, ptr, parentPtr);
+ }
+ if (!m_maxAsyncCallStackDepth) return;
switch (type) {
case v8::debug::kDebugPromiseCreated:
- asyncTaskCreated(
- ptr, parentId ? reinterpret_cast<void*>(parentId * 2 + 1) : nullptr);
+ asyncTaskCreated(ptr, parentPtr);
break;
case v8::debug::kDebugEnqueueAsyncFunction:
asyncTaskScheduled("async function", ptr, true);
@@ -658,6 +691,37 @@ void V8Debugger::PromiseEventOccurred(v8::debug::PromiseDebugActionType type,
}
}
+void V8Debugger::steppingOnPromiseEvent(v8::Local<v8::Context> context,
+ v8::debug::PromiseDebugActionType type,
+ void* task, void* parentPtr) {
+ if (type == v8::debug::kDebugPromiseCollected) {
+ m_tasksWithScheduledBreak.erase(task);
+ return;
+ }
+ DCHECK(!context.IsEmpty());
+ v8::Context::Scope contextScope(context);
+ V8DebuggerAgentImpl* agent =
+ m_inspector->enabledDebuggerAgentForGroup(currentContextGroupId());
+ if (!agent) return;
+ if (type == v8::debug::kDebugPromiseCreated) {
+ if (!parentPtr) return;
+ m_createdPromiseTask = task;
+ agent->breakProgramIfSteppingInto(
+ protocol::Debugger::Paused::ReasonEnum::Other, nullptr);
+ m_createdPromiseTask = nullptr;
+ return;
+ }
+ if (m_tasksWithScheduledBreak.find(task) == m_tasksWithScheduledBreak.end()) {
+ return;
+ }
+ if (type == v8::debug::kDebugWillHandle) {
+ agent->schedulePauseOnNextStatement(
+ protocol::Debugger::Paused::ReasonEnum::Other, nullptr);
+ } else {
+ agent->cancelPauseOnNextStatement();
+ }
+}
+
V8StackTraceImpl* V8Debugger::currentAsyncCallChain() {
if (!m_currentStacks.size()) return nullptr;
return m_currentStacks.back().get();
@@ -802,11 +866,7 @@ v8::MaybeLocal<v8::Array> V8Debugger::internalProperties(
std::unique_ptr<V8StackTraceImpl> V8Debugger::createStackTrace(
v8::Local<v8::StackTrace> stackTrace) {
- int contextGroupId =
- m_isolate->InContext()
- ? m_inspector->contextGroupId(m_isolate->GetCurrentContext())
- : 0;
- return V8StackTraceImpl::create(this, contextGroupId, stackTrace,
+ return V8StackTraceImpl::create(this, currentContextGroupId(), stackTrace,
V8StackTraceImpl::maxCallStackSizeToCapture);
}
@@ -843,7 +903,7 @@ void V8Debugger::asyncTaskCreated(void* task, void* parentTask) {
if (!m_maxAsyncCallStackDepth) return;
if (parentTask) m_parentTask[task] = parentTask;
v8::HandleScope scope(m_isolate);
- // We don't need to pass context group id here because we gets this callback
+ // We don't need to pass context group id here because we get this callback
// from V8 for promise events only.
// Passing one as maxStackSize forces no async chain for the new stack and
// allows us to not grow exponentially.
@@ -865,13 +925,9 @@ void V8Debugger::asyncTaskScheduled(const String16& taskName, void* task,
bool recurring) {
if (!m_maxAsyncCallStackDepth) return;
v8::HandleScope scope(m_isolate);
- int contextGroupId =
- m_isolate->InContext()
- ? m_inspector->contextGroupId(m_isolate->GetCurrentContext())
- : 0;
std::unique_ptr<V8StackTraceImpl> chain = V8StackTraceImpl::capture(
- this, contextGroupId, V8StackTraceImpl::maxCallStackSizeToCapture,
- taskName);
+ this, currentContextGroupId(),
+ V8StackTraceImpl::maxCallStackSizeToCapture, taskName);
if (chain) {
m_asyncTaskStacks[task] = std::move(chain);
if (recurring) m_recurringTasks.insert(task);
@@ -954,8 +1010,7 @@ std::unique_ptr<V8StackTraceImpl> V8Debugger::captureStackTrace(
if (!m_isolate->InContext()) return nullptr;
v8::HandleScope handles(m_isolate);
- int contextGroupId =
- m_inspector->contextGroupId(m_isolate->GetCurrentContext());
+ int contextGroupId = currentContextGroupId();
if (!contextGroupId) return nullptr;
size_t stackSize =
@@ -966,4 +1021,9 @@ std::unique_ptr<V8StackTraceImpl> V8Debugger::captureStackTrace(
return V8StackTraceImpl::capture(this, contextGroupId, stackSize);
}
+int V8Debugger::currentContextGroupId() {
+ if (!m_isolate->InContext()) return 0;
+ return m_inspector->contextGroupId(m_isolate->GetCurrentContext());
+}
+
} // namespace v8_inspector
« 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