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 |