Chromium Code Reviews| 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 |