Chromium Code Reviews| Index: src/inspector/v8-debugger.cc |
| diff --git a/src/inspector/v8-debugger.cc b/src/inspector/v8-debugger.cc |
| index 3a2fc89f0039869b49a3c5cef4f4b92eab0017a6..d9876aedfad8669fff7d4113e69f9736009aff03 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_taskWithScheduledBreak = nullptr; |
| m_wasmTranslation.Clear(); |
| v8::debug::SetDebugDelegate(m_isolate, nullptr); |
| v8::debug::SetOutOfMemoryCallback(m_isolate, nullptr, nullptr); |
| @@ -625,17 +626,21 @@ 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 createdByUser) { |
| // 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; |
| + handleAsyncTaskStepping(context, type, ptr, parentPtr, createdByUser); |
| + 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 +663,36 @@ void V8Debugger::PromiseEventOccurred(v8::debug::PromiseDebugActionType type, |
| } |
| } |
| +void V8Debugger::handleAsyncTaskStepping(v8::Local<v8::Context> context, |
| + v8::debug::PromiseDebugActionType type, |
| + void* task, void* parentTask, |
| + bool createdByUser) { |
| + bool isScheduledTask = task == m_taskWithScheduledBreak; |
| + if (type == v8::debug::kDebugPromiseCollected) { |
| + if (isScheduledTask) m_taskWithScheduledBreak = nullptr; |
| + return; |
| + } |
| + if (type == v8::debug::kDebugPromiseCreated && !parentTask) return; |
| + |
| + DCHECK(!context.IsEmpty()); |
| + int contextGroupId = m_inspector->contextGroupId(context); |
| + V8DebuggerAgentImpl* agent = |
| + m_inspector->enabledDebuggerAgentForGroup(contextGroupId); |
| + if (!agent) return; |
| + if (createdByUser && type == v8::debug::kDebugPromiseCreated) { |
| + if (agent->shouldBreakInScheduledAsyncTask()) { |
| + m_taskWithScheduledBreak = task; |
| + } |
|
dgozman
2017/03/03 19:47:06
return;
kozy
2017/03/03 23:14:02
Done.
|
| + } else if (isScheduledTask && type == v8::debug::kDebugWillHandle) { |
| + agent->schedulePauseOnNextStatement( |
| + protocol::Debugger::Paused::ReasonEnum::Other, nullptr); |
| + } else if (isScheduledTask) { |
|
dgozman
2017/03/03 19:47:06
return;
kozy
2017/03/03 23:14:02
Done.
|
| + DCHECK(type == v8::debug::kDebugDidHandle); |
| + agent->cancelPauseOnNextStatement(); |
|
dgozman
2017/03/03 19:47:06
Would that interfere with stepping? Should we even
kozy
2017/03/03 23:14:02
Should not interfere with traditional stepping and
|
| + m_taskWithScheduledBreak = nullptr; |
| + } |
| +} |
| + |
| V8StackTraceImpl* V8Debugger::currentAsyncCallChain() { |
| if (!m_currentStacks.size()) return nullptr; |
| return m_currentStacks.back().get(); |
| @@ -802,11 +837,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 +874,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 +896,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 +981,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 +992,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 |