Chromium Code Reviews| Index: src/inspector/v8-debugger.cc |
| diff --git a/src/inspector/v8-debugger.cc b/src/inspector/v8-debugger.cc |
| index f4c3ca5813a05249ba56d1278fde1a9561ddee80..2668df89289820d54c413d4c513ba8864d35f255 100644 |
| --- a/src/inspector/v8-debugger.cc |
| +++ b/src/inspector/v8-debugger.cc |
| @@ -335,7 +335,10 @@ void V8Debugger::setPauseOnNextStatement(bool pause, int targetContextGroupId) { |
| m_targetContextGroupId != targetContextGroupId) { |
| return; |
| } |
| + DCHECK(m_targetContextGroupId == targetContextGroupId || |
| + !m_targetContextGroupId); |
| m_targetContextGroupId = targetContextGroupId; |
| + m_breakRequested = pause; |
| if (pause) |
| v8::debug::DebugBreak(m_isolate); |
| else |
| @@ -364,6 +367,8 @@ void V8Debugger::stepIntoStatement(int targetContextGroupId) { |
| DCHECK(isPaused()); |
| DCHECK(!m_executionState.IsEmpty()); |
| DCHECK(targetContextGroupId); |
| + DCHECK(m_targetContextGroupId == targetContextGroupId || |
| + !m_targetContextGroupId); |
|
dgozman
2017/03/28 23:20:50
Merge with previous DCHECK and simplify it :-)
kozy
2017/03/28 23:49:49
this dcheck is redundant so removed.
|
| m_targetContextGroupId = targetContextGroupId; |
| v8::debug::PrepareStep(m_isolate, v8::debug::StepIn); |
| continueProgram(); |
| @@ -373,6 +378,8 @@ void V8Debugger::stepOverStatement(int targetContextGroupId) { |
| DCHECK(isPaused()); |
| DCHECK(!m_executionState.IsEmpty()); |
| DCHECK(targetContextGroupId); |
| + DCHECK(m_targetContextGroupId == targetContextGroupId || |
|
dgozman
2017/03/28 23:20:50
everywhere
kozy
2017/03/28 23:49:49
Done.
|
| + !m_targetContextGroupId); |
| m_targetContextGroupId = targetContextGroupId; |
| v8::debug::PrepareStep(m_isolate, v8::debug::StepNext); |
| continueProgram(); |
| @@ -382,11 +389,27 @@ void V8Debugger::stepOutOfFunction(int targetContextGroupId) { |
| DCHECK(isPaused()); |
| DCHECK(!m_executionState.IsEmpty()); |
| DCHECK(targetContextGroupId); |
| + DCHECK(m_targetContextGroupId == targetContextGroupId || |
| + !m_targetContextGroupId); |
| m_targetContextGroupId = targetContextGroupId; |
| v8::debug::PrepareStep(m_isolate, v8::debug::StepOut); |
| continueProgram(); |
| } |
| +void V8Debugger::scheduleStepIntoAsync( |
| + std::unique_ptr<ScheduleStepIntoAsyncCallback> callback, |
| + int targetContextGroupId) { |
| + DCHECK(isPaused()); |
| + DCHECK(!m_executionState.IsEmpty()); |
| + DCHECK(targetContextGroupId); |
| + if (m_stepIntoAsyncCallback) { |
| + m_stepIntoAsyncCallback->sendFailure(Response::Error( |
| + "Current scheduled step into async was overriden with new one.")); |
| + } |
| + m_targetContextGroupId = targetContextGroupId; |
| + m_stepIntoAsyncCallback = std::move(callback); |
| +} |
| + |
| Response V8Debugger::setScriptSource( |
| const String16& sourceID, v8::Local<v8::String> newSource, bool dryRun, |
| Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails, |
| @@ -522,6 +545,11 @@ void V8Debugger::handleProgramBreak(v8::Local<v8::Context> pausedContext, |
| return; |
| } |
| m_targetContextGroupId = 0; |
| + if (m_stepIntoAsyncCallback) { |
| + m_stepIntoAsyncCallback->sendFailure( |
| + Response::Error("No async tasks were scheduled before pause.")); |
| + m_stepIntoAsyncCallback.reset(); |
| + } |
| V8DebuggerAgentImpl* agent = m_inspector->enabledDebuggerAgentForGroup( |
| m_inspector->contextGroupId(pausedContext)); |
| if (!agent || (agent->skipAllPauses() && !m_scheduledOOMBreak)) return; |
| @@ -633,25 +661,25 @@ void V8Debugger::PromiseEventOccurred(v8::Local<v8::Context> context, |
| if (!m_maxAsyncCallStackDepth) return; |
| switch (type) { |
| case v8::debug::kDebugPromiseCreated: |
| - asyncTaskCreated(ptr, parentPtr); |
| + asyncTaskCreatedForStack(ptr, parentPtr); |
| break; |
| case v8::debug::kDebugEnqueueAsyncFunction: |
| - asyncTaskScheduled("async function", ptr, true); |
| + asyncTaskScheduledForStack("async function", ptr, true); |
| break; |
| case v8::debug::kDebugEnqueuePromiseResolve: |
| - asyncTaskScheduled("Promise.resolve", ptr, true); |
| + asyncTaskScheduledForStack("Promise.resolve", ptr, true); |
| break; |
| case v8::debug::kDebugEnqueuePromiseReject: |
| - asyncTaskScheduled("Promise.reject", ptr, true); |
| + asyncTaskScheduledForStack("Promise.reject", ptr, true); |
| break; |
| case v8::debug::kDebugPromiseCollected: |
| - asyncTaskCanceled(ptr); |
| + asyncTaskCanceledForStack(ptr); |
| break; |
| case v8::debug::kDebugWillHandle: |
| - asyncTaskStarted(ptr); |
| + asyncTaskStartedForStack(ptr); |
| break; |
| case v8::debug::kDebugDidHandle: |
| - asyncTaskFinished(ptr); |
| + asyncTaskFinishedForStack(ptr); |
| break; |
| } |
| } |
| @@ -679,20 +707,21 @@ void V8Debugger::handleAsyncTaskStepping(v8::Local<v8::Context> context, |
| m_inspector->enabledDebuggerAgentForGroup(contextGroupId); |
| if (!agent) return; |
| if (createdByUser && type == v8::debug::kDebugPromiseCreated) { |
| - if (agent->shouldBreakInScheduledAsyncTask()) { |
| + if (contextGroupId == m_targetContextGroupId && m_stepIntoAsyncCallback) { |
| m_taskWithScheduledBreak = task; |
| v8::debug::ClearStepping(m_isolate); |
| + m_stepIntoAsyncCallback->sendSuccess(); |
| + m_stepIntoAsyncCallback.reset(); |
| } |
| return; |
| } |
| if (!isScheduledTask) return; |
| if (type == v8::debug::kDebugWillHandle) { |
| - agent->schedulePauseOnNextStatement( |
| - protocol::Debugger::Paused::ReasonEnum::Other, nullptr); |
| + if (!m_breakRequested) v8::debug::DebugBreak(m_isolate); |
| return; |
| } |
| DCHECK(type == v8::debug::kDebugDidHandle); |
| - agent->cancelPauseOnNextStatement(); |
| + if (!m_breakRequested) v8::debug::CancelDebugBreak(m_isolate); |
| m_taskWithScheduledBreak = nullptr; |
| } |
| @@ -869,11 +898,11 @@ void V8Debugger::registerAsyncTaskIfNeeded(void* task) { |
| m_idToTask[id] = task; |
| if (static_cast<int>(m_idToTask.size()) > m_maxAsyncCallStacks) { |
| void* taskToRemove = m_idToTask.begin()->second; |
| - asyncTaskCanceled(taskToRemove); |
| + asyncTaskCanceledForStack(taskToRemove); |
| } |
| } |
| -void V8Debugger::asyncTaskCreated(void* task, void* parentTask) { |
| +void V8Debugger::asyncTaskCreatedForStack(void* task, void* parentTask) { |
| if (!m_maxAsyncCallStackDepth) return; |
| if (parentTask) m_parentTask[task] = parentTask; |
| v8::HandleScope scope(m_isolate); |
| @@ -891,12 +920,39 @@ void V8Debugger::asyncTaskCreated(void* task, void* parentTask) { |
| void V8Debugger::asyncTaskScheduled(const StringView& taskName, void* task, |
| bool recurring) { |
| - if (!m_maxAsyncCallStackDepth) return; |
| - asyncTaskScheduled(toString16(taskName), task, recurring); |
| + asyncTaskScheduledForStack(toString16(taskName), task, recurring); |
| + if (currentContextGroupId() == m_targetContextGroupId && |
| + m_stepIntoAsyncCallback) { |
| + m_taskWithScheduledBreak = task; |
| + v8::debug::ClearStepping(m_isolate); |
| + m_stepIntoAsyncCallback->sendSuccess(); |
| + m_stepIntoAsyncCallback.reset(); |
| + } |
| } |
| -void V8Debugger::asyncTaskScheduled(const String16& taskName, void* task, |
| - bool recurring) { |
| +void V8Debugger::asyncTaskCanceled(void* task) { |
| + asyncTaskCanceledForStack(task); |
| + if (task == m_taskWithScheduledBreak) { |
| + m_taskWithScheduledBreak = nullptr; |
| + } |
| +} |
| + |
| +void V8Debugger::asyncTaskStarted(void* task) { |
| + asyncTaskStartedForStack(task); |
| + if (task == m_taskWithScheduledBreak) { |
| + if (!m_breakRequested) v8::debug::DebugBreak(m_isolate); |
| + } |
| +} |
| + |
| +void V8Debugger::asyncTaskFinished(void* task) { |
| + asyncTaskFinishedForStack(task); |
| + if (task == m_taskWithScheduledBreak) { |
| + if (!m_breakRequested) v8::debug::CancelDebugBreak(m_isolate); |
| + } |
| +} |
| + |
| +void V8Debugger::asyncTaskScheduledForStack(const String16& taskName, |
| + void* task, bool recurring) { |
| if (!m_maxAsyncCallStackDepth) return; |
| v8::HandleScope scope(m_isolate); |
| std::unique_ptr<V8StackTraceImpl> chain = V8StackTraceImpl::capture( |
| @@ -909,7 +965,7 @@ void V8Debugger::asyncTaskScheduled(const String16& taskName, void* task, |
| } |
| } |
| -void V8Debugger::asyncTaskCanceled(void* task) { |
| +void V8Debugger::asyncTaskCanceledForStack(void* task) { |
| if (!m_maxAsyncCallStackDepth) return; |
| m_asyncTaskStacks.erase(task); |
| m_recurringTasks.erase(task); |
| @@ -921,7 +977,7 @@ void V8Debugger::asyncTaskCanceled(void* task) { |
| m_taskToId.erase(it); |
| } |
| -void V8Debugger::asyncTaskStarted(void* task) { |
| +void V8Debugger::asyncTaskStartedForStack(void* task) { |
| if (!m_maxAsyncCallStackDepth) return; |
| m_currentTasks.push_back(task); |
| auto parentIt = m_parentTask.find(task); |
| @@ -944,7 +1000,7 @@ void V8Debugger::asyncTaskStarted(void* task) { |
| m_currentStacks.push_back(std::move(stack)); |
| } |
| -void V8Debugger::asyncTaskFinished(void* task) { |
| +void V8Debugger::asyncTaskFinishedForStack(void* task) { |
| if (!m_maxAsyncCallStackDepth) return; |
| // We could start instrumenting half way and the stack is empty. |
| if (!m_currentStacks.size()) return; |
| @@ -954,7 +1010,7 @@ void V8Debugger::asyncTaskFinished(void* task) { |
| m_currentStacks.pop_back(); |
| if (m_recurringTasks.find(task) == m_recurringTasks.end()) { |
| - asyncTaskCanceled(task); |
| + asyncTaskCanceledForStack(task); |
| } |
| } |