OLD | NEW |
---|---|
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/inspector/v8-debugger.h" | 5 #include "src/inspector/v8-debugger.h" |
6 | 6 |
7 #include "src/inspector/debugger-script.h" | 7 #include "src/inspector/debugger-script.h" |
8 #include "src/inspector/inspected-context.h" | 8 #include "src/inspector/inspected-context.h" |
9 #include "src/inspector/protocol/Protocol.h" | 9 #include "src/inspector/protocol/Protocol.h" |
10 #include "src/inspector/script-breakpoint.h" | 10 #include "src/inspector/script-breakpoint.h" |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
64 | 64 |
65 V8Debugger::~V8Debugger() {} | 65 V8Debugger::~V8Debugger() {} |
66 | 66 |
67 void V8Debugger::enable() { | 67 void V8Debugger::enable() { |
68 if (m_enableCount++) return; | 68 if (m_enableCount++) return; |
69 DCHECK(!enabled()); | 69 DCHECK(!enabled()); |
70 v8::HandleScope scope(m_isolate); | 70 v8::HandleScope scope(m_isolate); |
71 v8::debug::SetDebugEventListener(m_isolate, this); | 71 v8::debug::SetDebugEventListener(m_isolate, this); |
72 v8::debug::SetOutOfMemoryCallback(m_isolate, &V8Debugger::v8OOMCallback, | 72 v8::debug::SetOutOfMemoryCallback(m_isolate, &V8Debugger::v8OOMCallback, |
73 this); | 73 this); |
74 v8::debug::SetIsBlackboxedCallback(m_isolate, | |
75 &V8Debugger::v8IsBlackboxedCallback, this); | |
74 m_debuggerContext.Reset(m_isolate, v8::debug::GetDebugContext(m_isolate)); | 76 m_debuggerContext.Reset(m_isolate, v8::debug::GetDebugContext(m_isolate)); |
75 v8::debug::ChangeBreakOnException(m_isolate, v8::debug::NoBreakOnException); | 77 v8::debug::ChangeBreakOnException(m_isolate, v8::debug::NoBreakOnException); |
76 m_pauseOnExceptionsState = v8::debug::NoBreakOnException; | 78 m_pauseOnExceptionsState = v8::debug::NoBreakOnException; |
77 compileDebuggerScript(); | 79 compileDebuggerScript(); |
78 } | 80 } |
79 | 81 |
80 void V8Debugger::disable() { | 82 void V8Debugger::disable() { |
81 if (--m_enableCount) return; | 83 if (--m_enableCount) return; |
82 DCHECK(enabled()); | 84 DCHECK(enabled()); |
83 clearBreakpoints(); | 85 clearBreakpoints(); |
84 m_debuggerScript.Reset(); | 86 m_debuggerScript.Reset(); |
85 m_debuggerContext.Reset(); | 87 m_debuggerContext.Reset(); |
86 allAsyncTasksCanceled(); | 88 allAsyncTasksCanceled(); |
87 m_wasmTranslation.Clear(); | 89 m_wasmTranslation.Clear(); |
88 v8::debug::SetDebugEventListener(m_isolate, nullptr); | 90 v8::debug::SetDebugEventListener(m_isolate, nullptr); |
91 v8::debug::SetIsBlackboxedCallback(m_isolate, nullptr, nullptr); | |
89 v8::debug::SetOutOfMemoryCallback(m_isolate, nullptr, nullptr); | 92 v8::debug::SetOutOfMemoryCallback(m_isolate, nullptr, nullptr); |
90 m_isolate->RestoreOriginalHeapLimit(); | 93 m_isolate->RestoreOriginalHeapLimit(); |
91 } | 94 } |
92 | 95 |
93 bool V8Debugger::enabled() const { return !m_debuggerScript.IsEmpty(); } | 96 bool V8Debugger::enabled() const { return !m_debuggerScript.IsEmpty(); } |
94 | 97 |
95 void V8Debugger::getCompiledScripts( | 98 void V8Debugger::getCompiledScripts( |
96 int contextGroupId, | 99 int contextGroupId, |
97 std::vector<std::unique_ptr<V8DebuggerScript>>& result) { | 100 std::vector<std::unique_ptr<V8DebuggerScript>>& result) { |
98 v8::HandleScope scope(m_isolate); | 101 v8::HandleScope scope(m_isolate); |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
236 void V8Debugger::setPauseOnNextStatement(bool pause) { | 239 void V8Debugger::setPauseOnNextStatement(bool pause) { |
237 if (m_runningNestedMessageLoop) return; | 240 if (m_runningNestedMessageLoop) return; |
238 if (pause) | 241 if (pause) |
239 v8::debug::DebugBreak(m_isolate); | 242 v8::debug::DebugBreak(m_isolate); |
240 else | 243 else |
241 v8::debug::CancelDebugBreak(m_isolate); | 244 v8::debug::CancelDebugBreak(m_isolate); |
242 } | 245 } |
243 | 246 |
244 bool V8Debugger::canBreakProgram() { | 247 bool V8Debugger::canBreakProgram() { |
245 if (!m_breakpointsActivated) return false; | 248 if (!m_breakpointsActivated) return false; |
246 return m_isolate->InContext(); | 249 return v8::debug::HasUserFrameOnStack(m_isolate); |
250 } | |
251 | |
252 bool V8Debugger::hasUserFrameOnStack() { | |
253 return v8::debug::HasUserFrameOnStack(m_isolate); | |
247 } | 254 } |
248 | 255 |
249 void V8Debugger::breakProgram() { | 256 void V8Debugger::breakProgram() { |
250 if (isPaused()) { | 257 if (isPaused()) { |
251 DCHECK(!m_runningNestedMessageLoop); | 258 DCHECK(!m_runningNestedMessageLoop); |
252 v8::Local<v8::Value> exception; | 259 v8::Local<v8::Value> exception; |
253 v8::Local<v8::Array> hitBreakpoints; | 260 v8::Local<v8::Array> hitBreakpoints; |
254 handleProgramBreak(m_pausedContext, m_executionState, exception, | 261 handleProgramBreak(m_pausedContext, m_executionState, exception, |
255 hitBreakpoints); | 262 hitBreakpoints); |
256 return; | 263 return; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
289 continueProgram(); | 296 continueProgram(); |
290 } | 297 } |
291 | 298 |
292 void V8Debugger::stepOutOfFunction() { | 299 void V8Debugger::stepOutOfFunction() { |
293 DCHECK(isPaused()); | 300 DCHECK(isPaused()); |
294 DCHECK(!m_executionState.IsEmpty()); | 301 DCHECK(!m_executionState.IsEmpty()); |
295 v8::debug::PrepareStep(m_isolate, v8::debug::StepOut); | 302 v8::debug::PrepareStep(m_isolate, v8::debug::StepOut); |
296 continueProgram(); | 303 continueProgram(); |
297 } | 304 } |
298 | 305 |
299 void V8Debugger::clearStepping() { | |
300 DCHECK(enabled()); | |
301 v8::debug::ClearStepping(m_isolate); | |
302 } | |
303 | |
304 Response V8Debugger::setScriptSource( | 306 Response V8Debugger::setScriptSource( |
305 const String16& sourceID, v8::Local<v8::String> newSource, bool dryRun, | 307 const String16& sourceID, v8::Local<v8::String> newSource, bool dryRun, |
306 Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails, | 308 Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails, |
307 JavaScriptCallFrames* newCallFrames, Maybe<bool>* stackChanged, | 309 JavaScriptCallFrames* newCallFrames, Maybe<bool>* stackChanged, |
308 bool* compileError) { | 310 bool* compileError) { |
309 class EnableLiveEditScope { | 311 class EnableLiveEditScope { |
310 public: | 312 public: |
311 explicit EnableLiveEditScope(v8::Isolate* isolate) : m_isolate(isolate) { | 313 explicit EnableLiveEditScope(v8::Isolate* isolate) : m_isolate(isolate) { |
312 v8::debug::SetLiveEditEnabled(m_isolate, true); | 314 v8::debug::SetLiveEditEnabled(m_isolate, true); |
313 inLiveEditScope = true; | 315 inLiveEditScope = true; |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
473 v8::Local<v8::Value> hitBreakpointNumber = | 475 v8::Local<v8::Value> hitBreakpointNumber = |
474 hitBreakpointNumbers->Get(debuggerContext(), i).ToLocalChecked(); | 476 hitBreakpointNumbers->Get(debuggerContext(), i).ToLocalChecked(); |
475 DCHECK(hitBreakpointNumber->IsInt32()); | 477 DCHECK(hitBreakpointNumber->IsInt32()); |
476 breakpointIds.push_back(String16::fromInteger( | 478 breakpointIds.push_back(String16::fromInteger( |
477 hitBreakpointNumber->Int32Value(debuggerContext()).FromJust())); | 479 hitBreakpointNumber->Int32Value(debuggerContext()).FromJust())); |
478 } | 480 } |
479 } | 481 } |
480 | 482 |
481 m_pausedContext = pausedContext; | 483 m_pausedContext = pausedContext; |
482 m_executionState = executionState; | 484 m_executionState = executionState; |
483 V8DebuggerAgentImpl::SkipPauseRequest result = | 485 bool result = |
dgozman
2017/01/19 21:49:14
result -> shouldPause
kozy
2017/01/20 02:32:37
Done.
| |
484 agent->didPause(pausedContext, exception, breakpointIds, | 486 agent->didPause(pausedContext, exception, breakpointIds, |
485 isPromiseRejection, isUncaught, m_scheduledOOMBreak); | 487 isPromiseRejection, isUncaught, m_scheduledOOMBreak); |
486 if (result == V8DebuggerAgentImpl::RequestNoSkip) { | 488 if (result) { |
487 m_runningNestedMessageLoop = true; | 489 m_runningNestedMessageLoop = true; |
488 int groupId = m_inspector->contextGroupId(pausedContext); | 490 int groupId = m_inspector->contextGroupId(pausedContext); |
489 DCHECK(groupId); | 491 DCHECK(groupId); |
490 v8::Context::Scope scope(pausedContext); | 492 v8::Context::Scope scope(pausedContext); |
491 v8::Local<v8::Context> context = m_isolate->GetCurrentContext(); | 493 v8::Local<v8::Context> context = m_isolate->GetCurrentContext(); |
492 CHECK(!context.IsEmpty() && | 494 CHECK(!context.IsEmpty() && |
493 context != v8::debug::GetDebugContext(m_isolate)); | 495 context != v8::debug::GetDebugContext(m_isolate)); |
494 m_inspector->client()->runMessageLoopOnPause(groupId); | 496 m_inspector->client()->runMessageLoopOnPause(groupId); |
495 // The agent may have been removed in the nested loop. | 497 // The agent may have been removed in the nested loop. |
496 agent = m_inspector->enabledDebuggerAgentForGroup( | 498 agent = m_inspector->enabledDebuggerAgentForGroup( |
497 m_inspector->contextGroupId(pausedContext)); | 499 m_inspector->contextGroupId(pausedContext)); |
498 if (agent) agent->didContinue(); | 500 if (agent) agent->didContinue(); |
499 m_runningNestedMessageLoop = false; | 501 m_runningNestedMessageLoop = false; |
500 } | 502 } |
501 if (m_scheduledOOMBreak) m_isolate->RestoreOriginalHeapLimit(); | 503 if (m_scheduledOOMBreak) m_isolate->RestoreOriginalHeapLimit(); |
502 m_scheduledOOMBreak = false; | 504 m_scheduledOOMBreak = false; |
503 m_pausedContext.Clear(); | 505 m_pausedContext.Clear(); |
504 m_executionState.Clear(); | 506 m_executionState.Clear(); |
505 | |
506 if (result == V8DebuggerAgentImpl::RequestStepFrame) { | |
507 v8::debug::PrepareStep(m_isolate, v8::debug::StepFrame); | |
508 } else if (result == V8DebuggerAgentImpl::RequestStepInto) { | |
509 v8::debug::PrepareStep(m_isolate, v8::debug::StepIn); | |
510 } else if (result == V8DebuggerAgentImpl::RequestStepOut) { | |
511 v8::debug::PrepareStep(m_isolate, v8::debug::StepOut); | |
512 } | |
513 } | 507 } |
514 | 508 |
515 void V8Debugger::v8OOMCallback(void* data) { | 509 void V8Debugger::v8OOMCallback(void* data) { |
516 V8Debugger* thisPtr = static_cast<V8Debugger*>(data); | 510 V8Debugger* thisPtr = static_cast<V8Debugger*>(data); |
517 thisPtr->m_isolate->IncreaseHeapLimitForDebugging(); | 511 thisPtr->m_isolate->IncreaseHeapLimitForDebugging(); |
518 thisPtr->m_scheduledOOMBreak = true; | 512 thisPtr->m_scheduledOOMBreak = true; |
519 thisPtr->setPauseOnNextStatement(true); | 513 thisPtr->setPauseOnNextStatement(true); |
520 } | 514 } |
521 | 515 |
522 void V8Debugger::ScriptCompiled(v8::Local<v8::debug::Script> script, | 516 void V8Debugger::ScriptCompiled(v8::Local<v8::debug::Script> script, |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
587 break; | 581 break; |
588 case v8::debug::kDebugWillHandle: | 582 case v8::debug::kDebugWillHandle: |
589 asyncTaskStarted(ptr); | 583 asyncTaskStarted(ptr); |
590 break; | 584 break; |
591 case v8::debug::kDebugDidHandle: | 585 case v8::debug::kDebugDidHandle: |
592 asyncTaskFinished(ptr); | 586 asyncTaskFinished(ptr); |
593 break; | 587 break; |
594 } | 588 } |
595 } | 589 } |
596 | 590 |
591 bool V8Debugger::v8IsBlackboxedCallback(v8::Local<v8::debug::Script> script, | |
592 const v8::debug::Location& start, | |
593 const v8::debug::Location& end, | |
594 void* data) { | |
595 V8Debugger* debugger = static_cast<V8Debugger*>(data); | |
596 v8::Local<v8::Value> contextData; | |
597 if (!script->ContextData().ToLocal(&contextData) || !contextData->IsInt32()) | |
598 return false; | |
599 int contextId = static_cast<int>(contextData.As<v8::Int32>()->Value()); | |
600 V8DebuggerAgentImpl* agent = | |
601 debugger->m_inspector->enabledDebuggerAgentForGroup(contextId); | |
dgozman
2017/01/19 21:49:15
again?
kozy
2017/01/20 02:32:37
extracted to not repeat again.
| |
602 if (!agent) return false; | |
603 return agent->isBlackboxed(String16::fromInteger(script->Id()), start, end); | |
dgozman
2017/01/19 21:49:15
Converting to string here is unfortunate.
kozy
2017/01/20 02:32:37
Acknowledged.
| |
604 } | |
605 | |
597 V8StackTraceImpl* V8Debugger::currentAsyncCallChain() { | 606 V8StackTraceImpl* V8Debugger::currentAsyncCallChain() { |
598 if (!m_currentStacks.size()) return nullptr; | 607 if (!m_currentStacks.size()) return nullptr; |
599 return m_currentStacks.back().get(); | 608 return m_currentStacks.back().get(); |
600 } | 609 } |
601 | 610 |
602 void V8Debugger::compileDebuggerScript() { | 611 void V8Debugger::compileDebuggerScript() { |
603 if (!m_debuggerScript.IsEmpty()) { | 612 if (!m_debuggerScript.IsEmpty()) { |
604 UNREACHABLE(); | 613 UNREACHABLE(); |
605 return; | 614 return; |
606 } | 615 } |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
962 | 971 |
963 size_t stackSize = | 972 size_t stackSize = |
964 fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1; | 973 fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1; |
965 if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) | 974 if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) |
966 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; | 975 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; |
967 | 976 |
968 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); | 977 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); |
969 } | 978 } |
970 | 979 |
971 } // namespace v8_inspector | 980 } // namespace v8_inspector |
OLD | NEW |