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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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, &V8Debugger::v8DebugEventCallback, | 71 v8::debug::SetDebugEventListener(m_isolate, &V8Debugger::v8DebugEventCallback, |
72 v8::External::New(m_isolate, this)); | 72 v8::External::New(m_isolate, this)); |
73 v8::debug::SetAsyncTaskListener(m_isolate, &V8Debugger::v8AsyncTaskListener, | 73 v8::debug::SetAsyncTaskListener(m_isolate, &V8Debugger::v8AsyncTaskListener, |
74 this); | 74 this); |
| 75 v8::debug::SetCompileEventListener(m_isolate, |
| 76 &V8Debugger::v8CompileEventListener, this); |
75 m_debuggerContext.Reset(m_isolate, v8::debug::GetDebugContext(m_isolate)); | 77 m_debuggerContext.Reset(m_isolate, v8::debug::GetDebugContext(m_isolate)); |
76 v8::debug::ChangeBreakOnException(m_isolate, v8::debug::NoBreakOnException); | 78 v8::debug::ChangeBreakOnException(m_isolate, v8::debug::NoBreakOnException); |
77 m_pauseOnExceptionsState = v8::debug::NoBreakOnException; | 79 m_pauseOnExceptionsState = v8::debug::NoBreakOnException; |
78 compileDebuggerScript(); | 80 compileDebuggerScript(); |
79 } | 81 } |
80 | 82 |
81 void V8Debugger::disable() { | 83 void V8Debugger::disable() { |
82 if (--m_enableCount) return; | 84 if (--m_enableCount) return; |
83 DCHECK(enabled()); | 85 DCHECK(enabled()); |
84 clearBreakpoints(); | 86 clearBreakpoints(); |
85 m_debuggerScript.Reset(); | 87 m_debuggerScript.Reset(); |
86 m_debuggerContext.Reset(); | 88 m_debuggerContext.Reset(); |
87 allAsyncTasksCanceled(); | 89 allAsyncTasksCanceled(); |
88 m_wasmTranslation.Clear(); | 90 m_wasmTranslation.Clear(); |
89 v8::debug::SetDebugEventListener(m_isolate, nullptr); | 91 v8::debug::SetDebugEventListener(m_isolate, nullptr); |
90 v8::debug::SetAsyncTaskListener(m_isolate, nullptr, nullptr); | 92 v8::debug::SetAsyncTaskListener(m_isolate, nullptr, nullptr); |
| 93 v8::debug::SetCompileEventListener(m_isolate, nullptr, nullptr); |
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); |
99 v8::PersistentValueVector<v8::debug::Script> scripts(m_isolate); | 102 v8::PersistentValueVector<v8::debug::Script> scripts(m_isolate); |
100 v8::debug::GetLoadedScripts(m_isolate, scripts); | 103 v8::debug::GetLoadedScripts(m_isolate, scripts); |
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
529 ->Call(m_isolate->GetCurrentContext(), object, 0, nullptr) | 532 ->Call(m_isolate->GetCurrentContext(), object, 0, nullptr) |
530 .ToLocalChecked(); | 533 .ToLocalChecked(); |
531 } | 534 } |
532 | 535 |
533 void V8Debugger::handleV8DebugEvent( | 536 void V8Debugger::handleV8DebugEvent( |
534 const v8::debug::EventDetails& eventDetails) { | 537 const v8::debug::EventDetails& eventDetails) { |
535 if (!enabled()) return; | 538 if (!enabled()) return; |
536 v8::HandleScope scope(m_isolate); | 539 v8::HandleScope scope(m_isolate); |
537 | 540 |
538 v8::DebugEvent event = eventDetails.GetEvent(); | 541 v8::DebugEvent event = eventDetails.GetEvent(); |
539 if (event != v8::Break && event != v8::Exception && | 542 if (event != v8::Break && event != v8::Exception) return; |
540 event != v8::AfterCompile && event != v8::CompileError) | |
541 return; | |
542 | 543 |
543 v8::Local<v8::Context> eventContext = eventDetails.GetEventContext(); | 544 v8::Local<v8::Context> eventContext = eventDetails.GetEventContext(); |
544 DCHECK(!eventContext.IsEmpty()); | 545 DCHECK(!eventContext.IsEmpty()); |
545 V8DebuggerAgentImpl* agent = m_inspector->enabledDebuggerAgentForGroup( | 546 V8DebuggerAgentImpl* agent = m_inspector->enabledDebuggerAgentForGroup( |
546 m_inspector->contextGroupId(eventContext)); | 547 m_inspector->contextGroupId(eventContext)); |
547 if (!agent) return; | 548 if (!agent) return; |
548 | 549 |
549 if (event == v8::AfterCompile || event == v8::CompileError) { | 550 if (event == v8::Exception) { |
550 v8::Context::Scope contextScope(debuggerContext()); | |
551 // Determine if the script is a wasm script. | |
552 v8::Local<v8::Value> scriptMirror = | |
553 callInternalGetterFunction(eventDetails.GetEventData(), "script"); | |
554 DCHECK(scriptMirror->IsObject()); | |
555 v8::Local<v8::Value> scriptWrapper = | |
556 callInternalGetterFunction(scriptMirror.As<v8::Object>(), "value"); | |
557 DCHECK(scriptWrapper->IsObject()); | |
558 v8::Local<v8::debug::Script> script; | |
559 if (!v8::debug::Script::Wrap(m_isolate, scriptWrapper.As<v8::Object>()) | |
560 .ToLocal(&script)) { | |
561 return; | |
562 } | |
563 if (script->IsWasm()) { | |
564 m_wasmTranslation.AddScript(script.As<v8::debug::WasmScript>(), agent); | |
565 } else if (m_ignoreScriptParsedEventsCounter == 0) { | |
566 agent->didParseSource( | |
567 V8DebuggerScript::Create(m_isolate, script, inLiveEditScope), | |
568 event == v8::AfterCompile); | |
569 } | |
570 } else if (event == v8::Exception) { | |
571 v8::Local<v8::Context> context = debuggerContext(); | 551 v8::Local<v8::Context> context = debuggerContext(); |
572 v8::Local<v8::Object> eventData = eventDetails.GetEventData(); | 552 v8::Local<v8::Object> eventData = eventDetails.GetEventData(); |
573 v8::Local<v8::Value> exception = | 553 v8::Local<v8::Value> exception = |
574 callInternalGetterFunction(eventData, "exception"); | 554 callInternalGetterFunction(eventData, "exception"); |
575 v8::Local<v8::Value> promise = | 555 v8::Local<v8::Value> promise = |
576 callInternalGetterFunction(eventData, "promise"); | 556 callInternalGetterFunction(eventData, "promise"); |
577 bool isPromiseRejection = !promise.IsEmpty() && promise->IsObject(); | 557 bool isPromiseRejection = !promise.IsEmpty() && promise->IsObject(); |
578 v8::Local<v8::Value> uncaught = | 558 v8::Local<v8::Value> uncaught = |
579 callInternalGetterFunction(eventData, "uncaught"); | 559 callInternalGetterFunction(eventData, "uncaught"); |
580 bool isUncaught = uncaught->BooleanValue(context).FromJust(); | 560 bool isUncaught = uncaught->BooleanValue(context).FromJust(); |
581 handleProgramBreak(eventContext, eventDetails.GetExecutionState(), | 561 handleProgramBreak(eventContext, eventDetails.GetExecutionState(), |
582 exception, v8::Local<v8::Array>(), isPromiseRejection, | 562 exception, v8::Local<v8::Array>(), isPromiseRejection, |
583 isUncaught); | 563 isUncaught); |
584 } else if (event == v8::Break) { | 564 } else if (event == v8::Break) { |
585 v8::Local<v8::Value> argv[] = {eventDetails.GetEventData()}; | 565 v8::Local<v8::Value> argv[] = {eventDetails.GetEventData()}; |
586 v8::Local<v8::Value> hitBreakpoints; | 566 v8::Local<v8::Value> hitBreakpoints; |
587 if (!callDebuggerMethod("getBreakpointNumbers", 1, argv) | 567 if (!callDebuggerMethod("getBreakpointNumbers", 1, argv) |
588 .ToLocal(&hitBreakpoints)) | 568 .ToLocal(&hitBreakpoints)) |
589 return; | 569 return; |
590 DCHECK(hitBreakpoints->IsArray()); | 570 DCHECK(hitBreakpoints->IsArray()); |
591 handleProgramBreak(eventContext, eventDetails.GetExecutionState(), | 571 handleProgramBreak(eventContext, eventDetails.GetExecutionState(), |
592 v8::Local<v8::Value>(), hitBreakpoints.As<v8::Array>()); | 572 v8::Local<v8::Value>(), hitBreakpoints.As<v8::Array>()); |
593 } | 573 } |
594 } | 574 } |
595 | 575 |
| 576 void V8Debugger::v8CompileEventListener(v8::Local<v8::debug::Script> script, |
| 577 bool has_compile_error, void* data) { |
| 578 V8Debugger* debugger = static_cast<V8Debugger*>(data); |
| 579 v8::Local<v8::Value> contextData; |
| 580 if (!script->ContextData().ToLocal(&contextData) || !contextData->IsInt32()) { |
| 581 return; |
| 582 } |
| 583 int contextId = static_cast<int>(contextData.As<v8::Int32>()->Value()); |
| 584 int contextGroupId = debugger->m_inspector->contextGroupId(contextId); |
| 585 if (!contextGroupId) return; |
| 586 V8DebuggerAgentImpl* agent = |
| 587 debugger->m_inspector->enabledDebuggerAgentForGroup(contextGroupId); |
| 588 if (!agent) return; |
| 589 if (script->IsWasm()) { |
| 590 debugger->m_wasmTranslation.AddScript(script.As<v8::debug::WasmScript>(), |
| 591 agent); |
| 592 } else if (debugger->m_ignoreScriptParsedEventsCounter == 0) { |
| 593 agent->didParseSource( |
| 594 V8DebuggerScript::Create(debugger->m_isolate, script, inLiveEditScope), |
| 595 !has_compile_error); |
| 596 } |
| 597 } |
| 598 |
596 void V8Debugger::v8AsyncTaskListener(v8::debug::PromiseDebugActionType type, | 599 void V8Debugger::v8AsyncTaskListener(v8::debug::PromiseDebugActionType type, |
597 int id, void* data) { | 600 int id, void* data) { |
598 V8Debugger* debugger = static_cast<V8Debugger*>(data); | 601 V8Debugger* debugger = static_cast<V8Debugger*>(data); |
599 if (!debugger->m_maxAsyncCallStackDepth) return; | 602 if (!debugger->m_maxAsyncCallStackDepth) return; |
600 // Async task events from Promises are given misaligned pointers to prevent | 603 // Async task events from Promises are given misaligned pointers to prevent |
601 // from overlapping with other Blink task identifiers. There is a single | 604 // from overlapping with other Blink task identifiers. There is a single |
602 // namespace of such ids, managed by src/js/promise.js. | 605 // namespace of such ids, managed by src/js/promise.js. |
603 void* ptr = reinterpret_cast<void*>(id * 2 + 1); | 606 void* ptr = reinterpret_cast<void*>(id * 2 + 1); |
604 switch (type) { | 607 switch (type) { |
605 case v8::debug::kDebugEnqueueAsyncFunction: | 608 case v8::debug::kDebugEnqueueAsyncFunction: |
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
994 | 997 |
995 size_t stackSize = | 998 size_t stackSize = |
996 fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1; | 999 fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1; |
997 if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) | 1000 if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) |
998 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; | 1001 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; |
999 | 1002 |
1000 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); | 1003 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); |
1001 } | 1004 } |
1002 | 1005 |
1003 } // namespace v8_inspector | 1006 } // namespace v8_inspector |
OLD | NEW |