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 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 this); | 183 this); |
184 m_debuggerContext.Reset(m_isolate, v8::debug::GetDebugContext(m_isolate)); | 184 m_debuggerContext.Reset(m_isolate, v8::debug::GetDebugContext(m_isolate)); |
185 v8::debug::ChangeBreakOnException(m_isolate, v8::debug::NoBreakOnException); | 185 v8::debug::ChangeBreakOnException(m_isolate, v8::debug::NoBreakOnException); |
186 m_pauseOnExceptionsState = v8::debug::NoBreakOnException; | 186 m_pauseOnExceptionsState = v8::debug::NoBreakOnException; |
187 compileDebuggerScript(); | 187 compileDebuggerScript(); |
188 } | 188 } |
189 | 189 |
190 void V8Debugger::disable() { | 190 void V8Debugger::disable() { |
191 if (--m_enableCount) return; | 191 if (--m_enableCount) return; |
192 DCHECK(enabled()); | 192 DCHECK(enabled()); |
193 clearBreakpoints(); | |
194 m_debuggerScript.Reset(); | 193 m_debuggerScript.Reset(); |
195 m_debuggerContext.Reset(); | 194 m_debuggerContext.Reset(); |
196 allAsyncTasksCanceled(); | 195 allAsyncTasksCanceled(); |
197 m_wasmTranslation.Clear(); | 196 m_wasmTranslation.Clear(); |
198 v8::debug::SetDebugDelegate(m_isolate, nullptr); | 197 v8::debug::SetDebugDelegate(m_isolate, nullptr); |
199 v8::debug::SetOutOfMemoryCallback(m_isolate, nullptr, nullptr); | 198 v8::debug::SetOutOfMemoryCallback(m_isolate, nullptr, nullptr); |
200 m_isolate->RestoreOriginalHeapLimit(); | 199 m_isolate->RestoreOriginalHeapLimit(); |
201 } | 200 } |
202 | 201 |
203 bool V8Debugger::enabled() const { return !m_debuggerScript.IsEmpty(); } | 202 bool V8Debugger::enabled() const { return !m_debuggerScript.IsEmpty(); } |
204 | 203 |
205 void V8Debugger::getCompiledScripts( | 204 void V8Debugger::getCompiledScripts( |
206 int contextGroupId, | 205 int contextGroupId, |
207 std::vector<std::unique_ptr<V8DebuggerScript>>& result) { | 206 std::vector<std::unique_ptr<V8DebuggerScript>>& result) { |
208 v8::HandleScope scope(m_isolate); | 207 v8::HandleScope scope(m_isolate); |
209 v8::PersistentValueVector<v8::debug::Script> scripts(m_isolate); | 208 v8::PersistentValueVector<v8::debug::Script> scripts(m_isolate); |
210 v8::debug::GetLoadedScripts(m_isolate, scripts); | 209 v8::debug::GetLoadedScripts(m_isolate, scripts); |
211 for (size_t i = 0; i < scripts.Size(); ++i) { | 210 for (size_t i = 0; i < scripts.Size(); ++i) { |
212 v8::Local<v8::debug::Script> script = scripts.Get(i); | 211 v8::Local<v8::debug::Script> script = scripts.Get(i); |
213 if (!script->WasCompiled()) continue; | 212 if (!script->WasCompiled()) continue; |
214 v8::Local<v8::Value> contextData; | 213 v8::Local<v8::Value> contextData; |
215 if (!script->ContextData().ToLocal(&contextData) || !contextData->IsInt32()) | 214 if (!script->ContextData().ToLocal(&contextData) || !contextData->IsInt32()) |
216 continue; | 215 continue; |
217 int contextId = static_cast<int>(contextData.As<v8::Int32>()->Value()); | 216 int contextId = static_cast<int>(contextData.As<v8::Int32>()->Value()); |
218 if (m_inspector->contextGroupId(contextId) != contextGroupId) continue; | 217 if (m_inspector->contextGroupId(contextId) != contextGroupId) continue; |
219 result.push_back(V8DebuggerScript::Create(m_isolate, script, false)); | 218 result.push_back(V8DebuggerScript::Create(m_isolate, script, false)); |
220 } | 219 } |
221 } | 220 } |
222 | 221 |
223 String16 V8Debugger::setBreakpoint(const ScriptBreakpoint& breakpoint, | |
224 int* actualLineNumber, | |
225 int* actualColumnNumber) { | |
226 v8::HandleScope scope(m_isolate); | |
227 v8::Local<v8::Context> context = debuggerContext(); | |
228 v8::Context::Scope contextScope(context); | |
229 | |
230 v8::Local<v8::Object> info = v8::Object::New(m_isolate); | |
231 bool success = false; | |
232 success = info->Set(context, toV8StringInternalized(m_isolate, "sourceID"), | |
233 toV8String(m_isolate, breakpoint.script_id)) | |
234 .FromMaybe(false); | |
235 DCHECK(success); | |
236 success = info->Set(context, toV8StringInternalized(m_isolate, "lineNumber"), | |
237 v8::Integer::New(m_isolate, breakpoint.line_number)) | |
238 .FromMaybe(false); | |
239 DCHECK(success); | |
240 success = | |
241 info->Set(context, toV8StringInternalized(m_isolate, "columnNumber"), | |
242 v8::Integer::New(m_isolate, breakpoint.column_number)) | |
243 .FromMaybe(false); | |
244 DCHECK(success); | |
245 success = info->Set(context, toV8StringInternalized(m_isolate, "condition"), | |
246 toV8String(m_isolate, breakpoint.condition)) | |
247 .FromMaybe(false); | |
248 DCHECK(success); | |
249 USE(success); | |
250 | |
251 v8::Local<v8::Function> setBreakpointFunction = v8::Local<v8::Function>::Cast( | |
252 m_debuggerScript.Get(m_isolate) | |
253 ->Get(context, toV8StringInternalized(m_isolate, "setBreakpoint")) | |
254 .ToLocalChecked()); | |
255 v8::Local<v8::Value> breakpointId = | |
256 v8::debug::Call(debuggerContext(), setBreakpointFunction, info) | |
257 .ToLocalChecked(); | |
258 if (!breakpointId->IsString()) return ""; | |
259 *actualLineNumber = | |
260 info->Get(context, toV8StringInternalized(m_isolate, "lineNumber")) | |
261 .ToLocalChecked() | |
262 ->Int32Value(context) | |
263 .FromJust(); | |
264 *actualColumnNumber = | |
265 info->Get(context, toV8StringInternalized(m_isolate, "columnNumber")) | |
266 .ToLocalChecked() | |
267 ->Int32Value(context) | |
268 .FromJust(); | |
269 return toProtocolString(breakpointId.As<v8::String>()); | |
270 } | |
271 | |
272 void V8Debugger::removeBreakpoint(const String16& breakpointId) { | |
273 v8::HandleScope scope(m_isolate); | |
274 v8::Local<v8::Context> context = debuggerContext(); | |
275 v8::Context::Scope contextScope(context); | |
276 | |
277 v8::Local<v8::Object> info = v8::Object::New(m_isolate); | |
278 bool success = false; | |
279 success = | |
280 info->Set(context, toV8StringInternalized(m_isolate, "breakpointId"), | |
281 toV8String(m_isolate, breakpointId)) | |
282 .FromMaybe(false); | |
283 DCHECK(success); | |
284 USE(success); | |
285 | |
286 v8::Local<v8::Function> removeBreakpointFunction = | |
287 v8::Local<v8::Function>::Cast( | |
288 m_debuggerScript.Get(m_isolate) | |
289 ->Get(context, | |
290 toV8StringInternalized(m_isolate, "removeBreakpoint")) | |
291 .ToLocalChecked()); | |
292 v8::debug::Call(debuggerContext(), removeBreakpointFunction, info) | |
293 .ToLocalChecked(); | |
294 } | |
295 | |
296 void V8Debugger::clearBreakpoints() { | |
297 v8::HandleScope scope(m_isolate); | |
298 v8::Local<v8::Context> context = debuggerContext(); | |
299 v8::Context::Scope contextScope(context); | |
300 | |
301 v8::Local<v8::Function> clearBreakpoints = v8::Local<v8::Function>::Cast( | |
302 m_debuggerScript.Get(m_isolate) | |
303 ->Get(context, toV8StringInternalized(m_isolate, "clearBreakpoints")) | |
304 .ToLocalChecked()); | |
305 v8::debug::Call(debuggerContext(), clearBreakpoints).ToLocalChecked(); | |
306 } | |
307 | |
308 void V8Debugger::setBreakpointsActivated(bool activated) { | 222 void V8Debugger::setBreakpointsActivated(bool activated) { |
309 if (!enabled()) { | 223 if (!enabled()) { |
310 UNREACHABLE(); | 224 UNREACHABLE(); |
311 return; | 225 return; |
312 } | 226 } |
313 v8::debug::SetBreakPointsActive(m_isolate, activated); | 227 v8::debug::SetBreakPointsActive(m_isolate, activated); |
314 m_breakpointsActivated = activated; | 228 m_breakpointsActivated = activated; |
315 } | 229 } |
316 | 230 |
317 v8::debug::ExceptionBreakState V8Debugger::getPauseOnExceptionsState() { | 231 v8::debug::ExceptionBreakState V8Debugger::getPauseOnExceptionsState() { |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 } | 424 } |
511 | 425 |
512 void V8Debugger::breakProgramCallback( | 426 void V8Debugger::breakProgramCallback( |
513 const v8::FunctionCallbackInfo<v8::Value>& info) { | 427 const v8::FunctionCallbackInfo<v8::Value>& info) { |
514 DCHECK_EQ(info.Length(), 2); | 428 DCHECK_EQ(info.Length(), 2); |
515 V8Debugger* thisPtr = toV8Debugger(info.Data()); | 429 V8Debugger* thisPtr = toV8Debugger(info.Data()); |
516 if (!thisPtr->enabled()) return; | 430 if (!thisPtr->enabled()) return; |
517 v8::Local<v8::Context> pausedContext = | 431 v8::Local<v8::Context> pausedContext = |
518 thisPtr->m_isolate->GetCurrentContext(); | 432 thisPtr->m_isolate->GetCurrentContext(); |
519 v8::Local<v8::Value> exception; | 433 v8::Local<v8::Value> exception; |
520 v8::Local<v8::Array> hitBreakpoints; | 434 v8::PersistentValueVector<v8::debug::BreakPoint> hitBreakpoints( |
| 435 thisPtr->m_isolate); |
521 thisPtr->handleProgramBreak(pausedContext, | 436 thisPtr->handleProgramBreak(pausedContext, |
522 v8::Local<v8::Object>::Cast(info[0]), exception, | 437 v8::Local<v8::Object>::Cast(info[0]), exception, |
523 hitBreakpoints); | 438 hitBreakpoints); |
524 } | 439 } |
525 | 440 |
526 void V8Debugger::handleProgramBreak(v8::Local<v8::Context> pausedContext, | 441 void V8Debugger::handleProgramBreak( |
527 v8::Local<v8::Object> executionState, | 442 v8::Local<v8::Context> pausedContext, v8::Local<v8::Object> executionState, |
528 v8::Local<v8::Value> exception, | 443 v8::Local<v8::Value> exception, |
529 v8::Local<v8::Array> hitBreakpointNumbers, | 444 const v8::PersistentValueVector<v8::debug::BreakPoint>& hitBreakPoints, |
530 bool isPromiseRejection, bool isUncaught) { | 445 bool isPromiseRejection, bool isUncaught) { |
531 // Don't allow nested breaks. | 446 // Don't allow nested breaks. |
532 if (isPaused()) return; | 447 if (isPaused()) return; |
533 | 448 |
534 V8DebuggerAgentImpl* agent = m_inspector->enabledDebuggerAgentForGroup( | 449 V8DebuggerAgentImpl* agent = m_inspector->enabledDebuggerAgentForGroup( |
535 m_inspector->contextGroupId(pausedContext)); | 450 m_inspector->contextGroupId(pausedContext)); |
536 if (!agent || (agent->skipAllPauses() && !m_scheduledOOMBreak)) return; | 451 if (!agent || (agent->skipAllPauses() && !m_scheduledOOMBreak)) return; |
537 | 452 |
538 std::vector<String16> breakpointIds; | |
539 if (!hitBreakpointNumbers.IsEmpty()) { | |
540 breakpointIds.reserve(hitBreakpointNumbers->Length()); | |
541 for (uint32_t i = 0; i < hitBreakpointNumbers->Length(); i++) { | |
542 v8::Local<v8::Value> hitBreakpointNumber = | |
543 hitBreakpointNumbers->Get(debuggerContext(), i).ToLocalChecked(); | |
544 DCHECK(hitBreakpointNumber->IsInt32()); | |
545 breakpointIds.push_back(String16::fromInteger( | |
546 hitBreakpointNumber->Int32Value(debuggerContext()).FromJust())); | |
547 } | |
548 } | |
549 | |
550 m_pausedContext = pausedContext; | 453 m_pausedContext = pausedContext; |
551 m_executionState = executionState; | 454 m_executionState = executionState; |
552 m_runningNestedMessageLoop = true; | 455 m_runningNestedMessageLoop = true; |
553 agent->didPause(InspectedContext::contextId(pausedContext), exception, | 456 agent->didPause(InspectedContext::contextId(pausedContext), exception, |
554 breakpointIds, isPromiseRejection, isUncaught, | 457 hitBreakPoints, isPromiseRejection, isUncaught, |
555 m_scheduledOOMBreak); | 458 m_scheduledOOMBreak); |
556 int groupId = m_inspector->contextGroupId(pausedContext); | 459 int groupId = m_inspector->contextGroupId(pausedContext); |
557 DCHECK(groupId); | 460 DCHECK(groupId); |
558 { | 461 { |
559 v8::Context::Scope scope(pausedContext); | 462 v8::Context::Scope scope(pausedContext); |
560 v8::Local<v8::Context> context = m_isolate->GetCurrentContext(); | 463 v8::Local<v8::Context> context = m_isolate->GetCurrentContext(); |
561 CHECK(!context.IsEmpty() && | 464 CHECK(!context.IsEmpty() && |
562 context != v8::debug::GetDebugContext(m_isolate)); | 465 context != v8::debug::GetDebugContext(m_isolate)); |
563 m_inspector->client()->runMessageLoopOnPause(groupId); | 466 m_inspector->client()->runMessageLoopOnPause(groupId); |
564 m_runningNestedMessageLoop = false; | 467 m_runningNestedMessageLoop = false; |
(...skipping 23 matching lines...) Expand all Loading... |
588 } else if (m_ignoreScriptParsedEventsCounter == 0) { | 491 } else if (m_ignoreScriptParsedEventsCounter == 0) { |
589 agent->didParseSource( | 492 agent->didParseSource( |
590 V8DebuggerScript::Create(m_isolate, script, inLiveEditScope), | 493 V8DebuggerScript::Create(m_isolate, script, inLiveEditScope), |
591 !has_compile_error); | 494 !has_compile_error); |
592 } | 495 } |
593 } | 496 } |
594 | 497 |
595 void V8Debugger::BreakProgramRequested(v8::Local<v8::Context> pausedContext, | 498 void V8Debugger::BreakProgramRequested(v8::Local<v8::Context> pausedContext, |
596 v8::Local<v8::Object> execState, | 499 v8::Local<v8::Object> execState, |
597 v8::Local<v8::Value> breakPointsHit) { | 500 v8::Local<v8::Value> breakPointsHit) { |
598 v8::Local<v8::Value> argv[] = {breakPointsHit}; | 501 v8::PersistentValueVector<v8::debug::BreakPoint> breakPoints(m_isolate); |
599 v8::Local<v8::Value> hitBreakpoints; | 502 if (!breakPointsHit->IsArray()) { |
600 if (!callDebuggerMethod("getBreakpointNumbers", 1, argv, true) | 503 handleProgramBreak(pausedContext, execState, v8::Local<v8::Value>(), |
601 .ToLocal(&hitBreakpoints)) { | 504 breakPoints); |
602 return; | 505 return; |
603 } | 506 } |
604 DCHECK(hitBreakpoints->IsArray()); | 507 v8::Local<v8::Array> breakPointsHitArray = |
| 508 v8::Local<v8::Array>::Cast(breakPointsHit); |
| 509 for (uint32_t i = 0; i < breakPointsHitArray->Length(); ++i) { |
| 510 v8::Local<v8::Value> item; |
| 511 if (!breakPointsHitArray->Get(pausedContext, i).ToLocal(&item)) continue; |
| 512 v8::Local<v8::debug::BreakPoint> breakPoint; |
| 513 if (!v8::debug::BreakPoint::Cast(m_isolate, item).ToLocal(&breakPoint)) { |
| 514 continue; |
| 515 } |
| 516 breakPoints.Append(breakPoint); |
| 517 } |
605 handleProgramBreak(pausedContext, execState, v8::Local<v8::Value>(), | 518 handleProgramBreak(pausedContext, execState, v8::Local<v8::Value>(), |
606 hitBreakpoints.As<v8::Array>()); | 519 breakPoints); |
607 } | 520 } |
608 | 521 |
609 void V8Debugger::ExceptionThrown(v8::Local<v8::Context> pausedContext, | 522 void V8Debugger::ExceptionThrown(v8::Local<v8::Context> pausedContext, |
610 v8::Local<v8::Object> execState, | 523 v8::Local<v8::Object> execState, |
611 v8::Local<v8::Value> exception, | 524 v8::Local<v8::Value> exception, |
612 v8::Local<v8::Value> promise, | 525 v8::Local<v8::Value> promise, |
613 bool isUncaught) { | 526 bool isUncaught) { |
614 bool isPromiseRejection = promise->IsPromise(); | 527 bool isPromiseRejection = promise->IsPromise(); |
615 handleProgramBreak(pausedContext, execState, exception, | 528 v8::PersistentValueVector<v8::debug::BreakPoint> hitBreakpoints(m_isolate); |
616 v8::Local<v8::Array>(), isPromiseRejection, isUncaught); | 529 handleProgramBreak(pausedContext, execState, exception, hitBreakpoints, |
| 530 isPromiseRejection, isUncaught); |
617 } | 531 } |
618 | 532 |
619 bool V8Debugger::IsFunctionBlackboxed(v8::Local<v8::debug::Script> script, | 533 bool V8Debugger::IsFunctionBlackboxed(v8::Local<v8::debug::Script> script, |
620 const v8::debug::Location& start, | 534 const v8::debug::Location& start, |
621 const v8::debug::Location& end) { | 535 const v8::debug::Location& end) { |
622 V8DebuggerAgentImpl* agent = agentForScript(m_inspector, script); | 536 V8DebuggerAgentImpl* agent = agentForScript(m_inspector, script); |
623 if (!agent) return false; | 537 if (!agent) return false; |
624 return agent->isFunctionBlackboxed(String16::fromInteger(script->Id()), start, | 538 return agent->isFunctionBlackboxed(String16::fromInteger(script->Id()), start, |
625 end); | 539 end); |
626 } | 540 } |
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
960 | 874 |
961 size_t stackSize = | 875 size_t stackSize = |
962 fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1; | 876 fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1; |
963 if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) | 877 if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) |
964 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; | 878 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; |
965 | 879 |
966 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); | 880 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); |
967 } | 881 } |
968 | 882 |
969 } // namespace v8_inspector | 883 } // namespace v8_inspector |
OLD | NEW |