| 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/protocol/Protocol.h" | 8 #include "src/inspector/protocol/Protocol.h" |
| 9 #include "src/inspector/script-breakpoint.h" | 9 #include "src/inspector/script-breakpoint.h" |
| 10 #include "src/inspector/string-util.h" | 10 #include "src/inspector/string-util.h" |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 49 | 49 |
| 50 V8Debugger::V8Debugger(v8::Isolate* isolate, V8InspectorImpl* inspector) | 50 V8Debugger::V8Debugger(v8::Isolate* isolate, V8InspectorImpl* inspector) |
| 51 : m_isolate(isolate), | 51 : m_isolate(isolate), |
| 52 m_inspector(inspector), | 52 m_inspector(inspector), |
| 53 m_lastContextId(0), | 53 m_lastContextId(0), |
| 54 m_enableCount(0), | 54 m_enableCount(0), |
| 55 m_breakpointsActivated(true), | 55 m_breakpointsActivated(true), |
| 56 m_runningNestedMessageLoop(false), | 56 m_runningNestedMessageLoop(false), |
| 57 m_ignoreScriptParsedEventsCounter(0), | 57 m_ignoreScriptParsedEventsCounter(0), |
| 58 m_maxAsyncCallStackDepth(0), | 58 m_maxAsyncCallStackDepth(0), |
| 59 m_pauseOnExceptionsState(v8::DebugInterface::NoBreakOnException) {} | 59 m_pauseOnExceptionsState(v8::DebugInterface::NoBreakOnException), |
| 60 m_wasmTranslation(isolate, this) {} |
| 60 | 61 |
| 61 V8Debugger::~V8Debugger() {} | 62 V8Debugger::~V8Debugger() {} |
| 62 | 63 |
| 63 void V8Debugger::enable() { | 64 void V8Debugger::enable() { |
| 64 if (m_enableCount++) return; | 65 if (m_enableCount++) return; |
| 65 DCHECK(!enabled()); | 66 DCHECK(!enabled()); |
| 66 v8::HandleScope scope(m_isolate); | 67 v8::HandleScope scope(m_isolate); |
| 67 v8::DebugInterface::SetDebugEventListener(m_isolate, | 68 v8::DebugInterface::SetDebugEventListener(m_isolate, |
| 68 &V8Debugger::v8DebugEventCallback, | 69 &V8Debugger::v8DebugEventCallback, |
| 69 v8::External::New(m_isolate, this)); | 70 v8::External::New(m_isolate, this)); |
| 70 m_debuggerContext.Reset(m_isolate, | 71 m_debuggerContext.Reset(m_isolate, |
| 71 v8::DebugInterface::GetDebugContext(m_isolate)); | 72 v8::DebugInterface::GetDebugContext(m_isolate)); |
| 72 v8::DebugInterface::ChangeBreakOnException( | 73 v8::DebugInterface::ChangeBreakOnException( |
| 73 m_isolate, v8::DebugInterface::NoBreakOnException); | 74 m_isolate, v8::DebugInterface::NoBreakOnException); |
| 74 m_pauseOnExceptionsState = v8::DebugInterface::NoBreakOnException; | 75 m_pauseOnExceptionsState = v8::DebugInterface::NoBreakOnException; |
| 75 compileDebuggerScript(); | 76 compileDebuggerScript(); |
| 76 } | 77 } |
| 77 | 78 |
| 78 void V8Debugger::disable() { | 79 void V8Debugger::disable() { |
| 79 if (--m_enableCount) return; | 80 if (--m_enableCount) return; |
| 80 DCHECK(enabled()); | 81 DCHECK(enabled()); |
| 81 clearBreakpoints(); | 82 clearBreakpoints(); |
| 82 m_debuggerScript.Reset(); | 83 m_debuggerScript.Reset(); |
| 83 m_debuggerContext.Reset(); | 84 m_debuggerContext.Reset(); |
| 84 allAsyncTasksCanceled(); | 85 allAsyncTasksCanceled(); |
| 86 m_wasmTranslation.Clear(); |
| 85 v8::DebugInterface::SetDebugEventListener(m_isolate, nullptr); | 87 v8::DebugInterface::SetDebugEventListener(m_isolate, nullptr); |
| 86 } | 88 } |
| 87 | 89 |
| 88 bool V8Debugger::enabled() const { return !m_debuggerScript.IsEmpty(); } | 90 bool V8Debugger::enabled() const { return !m_debuggerScript.IsEmpty(); } |
| 89 | 91 |
| 90 // static | 92 // static |
| 91 int V8Debugger::contextId(v8::Local<v8::Context> context) { | 93 int V8Debugger::contextId(v8::Local<v8::Context> context) { |
| 92 v8::Local<v8::Value> data = | 94 v8::Local<v8::Value> data = |
| 93 context->GetEmbedderData(static_cast<int>(v8::Context::kDebugIdIndex)); | 95 context->GetEmbedderData(static_cast<int>(v8::Context::kDebugIdIndex)); |
| 94 if (data.IsEmpty() || !data->IsString()) return 0; | 96 if (data.IsEmpty() || !data->IsString()) return 0; |
| (...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 567 | 569 |
| 568 if (event == v8::AsyncTaskEvent) { | 570 if (event == v8::AsyncTaskEvent) { |
| 569 v8::HandleScope scope(m_isolate); | 571 v8::HandleScope scope(m_isolate); |
| 570 handleV8AsyncTaskEvent(eventContext, eventDetails.GetExecutionState(), | 572 handleV8AsyncTaskEvent(eventContext, eventDetails.GetExecutionState(), |
| 571 eventDetails.GetEventData()); | 573 eventDetails.GetEventData()); |
| 572 return; | 574 return; |
| 573 } | 575 } |
| 574 | 576 |
| 575 V8DebuggerAgentImpl* agent = | 577 V8DebuggerAgentImpl* agent = |
| 576 m_inspector->enabledDebuggerAgentForGroup(getGroupId(eventContext)); | 578 m_inspector->enabledDebuggerAgentForGroup(getGroupId(eventContext)); |
| 577 if (agent) { | 579 if (!agent) return; |
| 578 v8::HandleScope scope(m_isolate); | 580 |
| 579 if (m_ignoreScriptParsedEventsCounter == 0 && | 581 v8::HandleScope scope(m_isolate); |
| 580 (event == v8::AfterCompile || event == v8::CompileError)) { | 582 if (event == v8::AfterCompile || event == v8::CompileError) { |
| 581 v8::Local<v8::Context> context = debuggerContext(); | 583 v8::Context::Scope contextScope(debuggerContext()); |
| 582 v8::Context::Scope contextScope(context); | 584 // Determine if the script is a wasm script. |
| 585 v8::Local<v8::Value> scriptMirror = |
| 586 callInternalGetterFunction(eventDetails.GetEventData(), "script"); |
| 587 DCHECK(scriptMirror->IsObject()); |
| 588 v8::Local<v8::Value> scriptWrapper = |
| 589 callInternalGetterFunction(scriptMirror.As<v8::Object>(), "value"); |
| 590 DCHECK(scriptWrapper->IsObject()); |
| 591 v8::Local<v8::DebugInterface::Script> script = |
| 592 v8::DebugInterface::Script::Wrap(m_isolate, |
| 593 scriptWrapper.As<v8::Object>()) |
| 594 .ToLocalChecked(); |
| 595 if (script->IsWasm()) { |
| 596 m_wasmTranslation.AddScript(scriptWrapper.As<v8::Object>()); |
| 597 } else if (m_ignoreScriptParsedEventsCounter == 0) { |
| 583 v8::Local<v8::Value> argv[] = {eventDetails.GetEventData()}; | 598 v8::Local<v8::Value> argv[] = {eventDetails.GetEventData()}; |
| 584 v8::Local<v8::Value> value = | 599 v8::Local<v8::Value> value = |
| 585 callDebuggerMethod("getAfterCompileScript", 1, argv).ToLocalChecked(); | 600 callDebuggerMethod("getAfterCompileScript", 1, argv).ToLocalChecked(); |
| 586 if (value->IsNull()) return; | 601 if (value->IsNull()) return; |
| 587 DCHECK(value->IsObject()); | 602 DCHECK(value->IsObject()); |
| 588 v8::Local<v8::Object> scriptObject = v8::Local<v8::Object>::Cast(value); | 603 v8::Local<v8::Object> scriptObject = v8::Local<v8::Object>::Cast(value); |
| 589 v8::Local<v8::DebugInterface::Script> script; | 604 v8::Local<v8::DebugInterface::Script> script; |
| 590 if (!v8::DebugInterface::Script::Wrap(m_isolate, scriptObject) | 605 if (!v8::DebugInterface::Script::Wrap(m_isolate, scriptObject) |
| 591 .ToLocal(&script)) | 606 .ToLocal(&script)) |
| 592 return; | 607 return; |
| 593 agent->didParseSource( | 608 agent->didParseSource( |
| 594 wrapUnique(new V8DebuggerScript(m_isolate, script, inLiveEditScope)), | 609 wrapUnique(new V8DebuggerScript(m_isolate, script, inLiveEditScope)), |
| 595 event == v8::AfterCompile); | 610 event == v8::AfterCompile); |
| 596 } else if (event == v8::Exception) { | |
| 597 v8::Local<v8::Context> context = debuggerContext(); | |
| 598 v8::Local<v8::Object> eventData = eventDetails.GetEventData(); | |
| 599 v8::Local<v8::Value> exception = | |
| 600 callInternalGetterFunction(eventData, "exception"); | |
| 601 v8::Local<v8::Value> promise = | |
| 602 callInternalGetterFunction(eventData, "promise"); | |
| 603 bool isPromiseRejection = !promise.IsEmpty() && promise->IsObject(); | |
| 604 v8::Local<v8::Value> uncaught = | |
| 605 callInternalGetterFunction(eventData, "uncaught"); | |
| 606 bool isUncaught = uncaught->BooleanValue(context).FromJust(); | |
| 607 handleProgramBreak(eventContext, eventDetails.GetExecutionState(), | |
| 608 exception, v8::Local<v8::Array>(), isPromiseRejection, | |
| 609 isUncaught); | |
| 610 } else if (event == v8::Break) { | |
| 611 v8::Local<v8::Value> argv[] = {eventDetails.GetEventData()}; | |
| 612 v8::Local<v8::Value> hitBreakpoints = | |
| 613 callDebuggerMethod("getBreakpointNumbers", 1, argv).ToLocalChecked(); | |
| 614 DCHECK(hitBreakpoints->IsArray()); | |
| 615 handleProgramBreak(eventContext, eventDetails.GetExecutionState(), | |
| 616 v8::Local<v8::Value>(), | |
| 617 hitBreakpoints.As<v8::Array>()); | |
| 618 } | 611 } |
| 612 } else if (event == v8::Exception) { |
| 613 v8::Local<v8::Context> context = debuggerContext(); |
| 614 v8::Local<v8::Object> eventData = eventDetails.GetEventData(); |
| 615 v8::Local<v8::Value> exception = |
| 616 callInternalGetterFunction(eventData, "exception"); |
| 617 v8::Local<v8::Value> promise = |
| 618 callInternalGetterFunction(eventData, "promise"); |
| 619 bool isPromiseRejection = !promise.IsEmpty() && promise->IsObject(); |
| 620 v8::Local<v8::Value> uncaught = |
| 621 callInternalGetterFunction(eventData, "uncaught"); |
| 622 bool isUncaught = uncaught->BooleanValue(context).FromJust(); |
| 623 handleProgramBreak(eventContext, eventDetails.GetExecutionState(), |
| 624 exception, v8::Local<v8::Array>(), isPromiseRejection, |
| 625 isUncaught); |
| 626 } else if (event == v8::Break) { |
| 627 v8::Local<v8::Value> argv[] = {eventDetails.GetEventData()}; |
| 628 v8::Local<v8::Value> hitBreakpoints = |
| 629 callDebuggerMethod("getBreakpointNumbers", 1, argv).ToLocalChecked(); |
| 630 DCHECK(hitBreakpoints->IsArray()); |
| 631 handleProgramBreak(eventContext, eventDetails.GetExecutionState(), |
| 632 v8::Local<v8::Value>(), hitBreakpoints.As<v8::Array>()); |
| 619 } | 633 } |
| 620 } | 634 } |
| 621 | 635 |
| 622 void V8Debugger::handleV8AsyncTaskEvent(v8::Local<v8::Context> context, | 636 void V8Debugger::handleV8AsyncTaskEvent(v8::Local<v8::Context> context, |
| 623 v8::Local<v8::Object> executionState, | 637 v8::Local<v8::Object> executionState, |
| 624 v8::Local<v8::Object> eventData) { | 638 v8::Local<v8::Object> eventData) { |
| 625 if (!m_maxAsyncCallStackDepth) return; | 639 if (!m_maxAsyncCallStackDepth) return; |
| 626 | 640 |
| 627 String16 type = toProtocolStringWithTypeCheck( | 641 String16 type = toProtocolStringWithTypeCheck( |
| 628 callInternalGetterFunction(eventData, "type")); | 642 callInternalGetterFunction(eventData, "type")); |
| (...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 977 | 991 |
| 978 size_t stackSize = | 992 size_t stackSize = |
| 979 fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1; | 993 fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1; |
| 980 if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) | 994 if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) |
| 981 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; | 995 stackSize = V8StackTraceImpl::maxCallStackSizeToCapture; |
| 982 | 996 |
| 983 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); | 997 return V8StackTraceImpl::capture(this, contextGroupId, stackSize); |
| 984 } | 998 } |
| 985 | 999 |
| 986 } // namespace v8_inspector | 1000 } // namespace v8_inspector |
| OLD | NEW |