Index: src/inspector/v8-debugger.cc |
diff --git a/src/inspector/v8-debugger.cc b/src/inspector/v8-debugger.cc |
index f4980e2f87e1de3d4916b2c526dd7c2c0d107b3b..f67066b89ef0c03727de64384c6a7e2987055a0f 100644 |
--- a/src/inspector/v8-debugger.cc |
+++ b/src/inspector/v8-debugger.cc |
@@ -298,6 +298,18 @@ void V8Debugger::stepIntoStatement() { |
continueProgram(); |
} |
+Response V8Debugger::stepIntoAsync() { |
+ DCHECK(isPaused()); |
+ DCHECK(!m_executionState.IsEmpty()); |
+ if (!m_currentCreatedAsyncTask) { |
+ return Response::Error("No scheduled chained callback"); |
+ } |
+ m_asyncTasksWithScheduledBreak.insert(m_currentCreatedAsyncTask); |
+ v8::debug::ClearStepping(m_isolate); |
+ continueProgram(); |
+ return Response::OK(); |
+} |
+ |
void V8Debugger::stepOverStatement() { |
DCHECK(isPaused()); |
DCHECK(!m_executionState.IsEmpty()); |
@@ -567,17 +579,13 @@ bool V8Debugger::IsFunctionBlackboxed(v8::Local<v8::debug::Script> script, |
} |
void V8Debugger::PromiseEventOccurred(v8::debug::PromiseDebugActionType type, |
- int id, int parentId) { |
+ int id) { |
if (!m_maxAsyncCallStackDepth) return; |
// 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); |
switch (type) { |
- case v8::debug::kDebugPromiseCreated: |
- asyncTaskCreated( |
- ptr, parentId ? reinterpret_cast<void*>(parentId * 2 + 1) : nullptr); |
- break; |
case v8::debug::kDebugEnqueueAsyncFunction: |
asyncTaskScheduled("async function", ptr, true); |
break; |
@@ -599,6 +607,32 @@ void V8Debugger::PromiseEventOccurred(v8::debug::PromiseDebugActionType type, |
} |
} |
+void V8Debugger::PromiseCreatedEvent(int id, int parentId, bool isBreakable) { |
+ if (!m_maxAsyncCallStackDepth) return; |
+ void* task = reinterpret_cast<void*>(id * 2 + 1); |
Yang
2017/01/30 19:40:33
why is this void* and not intptr_t?
|
+ void* parentTask = |
+ parentId ? reinterpret_cast<void*>(parentId * 2 + 1) : nullptr; |
+ 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 |
Yang
2017/01/30 19:40:33
s/gets/get/
kozy
2017/02/15 01:00:54
Done.
|
+ // 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. |
+ std::unique_ptr<V8StackTraceImpl> creationStack = |
+ V8StackTraceImpl::capture(this, 0, 1, String16()); |
+ if (creationStack && !creationStack->isEmpty()) { |
+ m_asyncTaskCreationStacks[task] = std::move(creationStack); |
+ registerAsyncTaskIfNeeded(task); |
+ } |
+ if (!parentTask || !isBreakable) return; |
+ V8DebuggerAgentImpl* agent = |
+ m_inspector->enabledDebuggerAgentForGroup(currentContextGroupId()); |
+ if (!agent) return; |
+ m_currentCreatedAsyncTask = task; |
+ agent->asyncTaskCreated(); |
+ m_currentCreatedAsyncTask = nullptr; |
+} |
+ |
V8StackTraceImpl* V8Debugger::currentAsyncCallChain() { |
if (!m_currentStacks.size()) return nullptr; |
return m_currentStacks.back().get(); |
@@ -837,11 +871,7 @@ bool V8Debugger::isPaused() { return !m_pausedContext.IsEmpty(); } |
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); |
} |
@@ -874,22 +904,6 @@ void V8Debugger::registerAsyncTaskIfNeeded(void* task) { |
} |
} |
-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 |
- // 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. |
- std::unique_ptr<V8StackTraceImpl> creationStack = |
- V8StackTraceImpl::capture(this, 0, 1, String16()); |
- if (creationStack && !creationStack->isEmpty()) { |
- m_asyncTaskCreationStacks[task] = std::move(creationStack); |
- registerAsyncTaskIfNeeded(task); |
- } |
-} |
- |
void V8Debugger::asyncTaskScheduled(const StringView& taskName, void* task, |
bool recurring) { |
if (!m_maxAsyncCallStackDepth) return; |
@@ -900,13 +914,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); |
@@ -920,6 +930,8 @@ void V8Debugger::asyncTaskCanceled(void* task) { |
m_recurringTasks.erase(task); |
m_parentTask.erase(task); |
m_asyncTaskCreationStacks.erase(task); |
+ if (m_currentCreatedAsyncTask == task) m_currentCreatedAsyncTask = nullptr; |
+ m_asyncTasksWithScheduledBreak.erase(task); |
auto it = m_taskToId.find(task); |
if (it == m_taskToId.end()) return; |
m_idToTask.erase(it->second); |
@@ -947,6 +959,13 @@ void V8Debugger::asyncTaskStarted(void* task) { |
stack->setCreation(itCreation->second->cloneImpl()); |
} |
m_currentStacks.push_back(std::move(stack)); |
+ if (m_asyncTasksWithScheduledBreak.find(task) == |
+ m_asyncTasksWithScheduledBreak.end()) |
+ return; |
+ V8DebuggerAgentImpl* agent = |
+ m_inspector->enabledDebuggerAgentForGroup(currentContextGroupId()); |
+ if (!agent) return; |
+ agent->asyncTaskStarted(); |
} |
void V8Debugger::asyncTaskFinished(void* task) { |
@@ -958,6 +977,15 @@ void V8Debugger::asyncTaskFinished(void* task) { |
m_currentTasks.pop_back(); |
m_currentStacks.pop_back(); |
+ if (m_asyncTasksWithScheduledBreak.find(task) != |
+ m_asyncTasksWithScheduledBreak.end()) { |
+ V8DebuggerAgentImpl* agent = |
+ m_inspector->enabledDebuggerAgentForGroup(currentContextGroupId()); |
+ if (!agent) return; |
+ agent->asyncTaskFinished(); |
+ m_asyncTasksWithScheduledBreak.erase(task); |
+ } |
+ |
if (m_recurringTasks.find(task) == m_recurringTasks.end()) { |
asyncTaskCanceled(task); |
} |
@@ -970,6 +998,8 @@ void V8Debugger::allAsyncTasksCanceled() { |
m_currentTasks.clear(); |
m_parentTask.clear(); |
m_asyncTaskCreationStacks.clear(); |
+ m_currentCreatedAsyncTask = nullptr; |
+ m_asyncTasksWithScheduledBreak.clear(); |
m_idToTask.clear(); |
m_taskToId.clear(); |
m_lastTaskId = 0; |
@@ -986,13 +1016,10 @@ void V8Debugger::unmuteScriptParsedEvents() { |
std::unique_ptr<V8StackTraceImpl> V8Debugger::captureStackTrace( |
bool fullStack) { |
- 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; |
+ v8::HandleScope handles(m_isolate); |
size_t stackSize = |
fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1; |
if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) |
@@ -1001,4 +1028,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 |