| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium 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 "platform/v8_inspector/V8StackTraceImpl.h" | 5 #include "platform/v8_inspector/V8StackTraceImpl.h" |
| 6 | 6 |
| 7 #include "platform/inspector_protocol/String16.h" | 7 #include "platform/inspector_protocol/String16.h" |
| 8 #include "platform/v8_inspector/V8DebuggerAgentImpl.h" | 8 #include "platform/v8_inspector/V8DebuggerAgentImpl.h" |
| 9 #include "platform/v8_inspector/V8DebuggerImpl.h" | 9 #include "platform/v8_inspector/V8DebuggerImpl.h" |
| 10 #include "platform/v8_inspector/V8StringUtil.h" | 10 #include "platform/v8_inspector/V8StringUtil.h" |
| 11 #include "wtf/PassOwnPtr.h" | 11 #include "wtf/PtrUtil.h" |
| 12 | 12 |
| 13 #include <v8-debug.h> | 13 #include <v8-debug.h> |
| 14 #include <v8-profiler.h> | 14 #include <v8-profiler.h> |
| 15 #include <v8-version.h> | 15 #include <v8-version.h> |
| 16 | 16 |
| 17 namespace blink { | 17 namespace blink { |
| 18 | 18 |
| 19 namespace { | 19 namespace { |
| 20 | 20 |
| 21 V8StackTraceImpl::Frame toFrame(v8::Local<v8::StackFrame> frame) | 21 V8StackTraceImpl::Frame toFrame(v8::Local<v8::StackFrame> frame) |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 67 , m_columnNumber(column) | 67 , m_columnNumber(column) |
| 68 { | 68 { |
| 69 } | 69 } |
| 70 | 70 |
| 71 V8StackTraceImpl::Frame::~Frame() | 71 V8StackTraceImpl::Frame::~Frame() |
| 72 { | 72 { |
| 73 } | 73 } |
| 74 | 74 |
| 75 // buildInspectorObject() and ScriptCallStack's toTracedValue() should set the s
ame fields. | 75 // buildInspectorObject() and ScriptCallStack's toTracedValue() should set the s
ame fields. |
| 76 // If either of them is modified, the other should be also modified. | 76 // If either of them is modified, the other should be also modified. |
| 77 PassOwnPtr<protocol::Runtime::CallFrame> V8StackTraceImpl::Frame::buildInspector
Object() const | 77 std::unique_ptr<protocol::Runtime::CallFrame> V8StackTraceImpl::Frame::buildInsp
ectorObject() const |
| 78 { | 78 { |
| 79 return protocol::Runtime::CallFrame::create() | 79 return protocol::Runtime::CallFrame::create() |
| 80 .setFunctionName(m_functionName) | 80 .setFunctionName(m_functionName) |
| 81 .setScriptId(m_scriptId) | 81 .setScriptId(m_scriptId) |
| 82 .setUrl(m_scriptName) | 82 .setUrl(m_scriptName) |
| 83 .setLineNumber(m_lineNumber) | 83 .setLineNumber(m_lineNumber) |
| 84 .setColumnNumber(m_columnNumber) | 84 .setColumnNumber(m_columnNumber) |
| 85 .build(); | 85 .build(); |
| 86 } | 86 } |
| 87 | 87 |
| 88 PassOwnPtr<V8StackTraceImpl> V8StackTraceImpl::create(V8DebuggerAgentImpl* agent
, v8::Local<v8::StackTrace> stackTrace, size_t maxStackSize, const String16& des
cription) | 88 std::unique_ptr<V8StackTraceImpl> V8StackTraceImpl::create(V8DebuggerAgentImpl*
agent, v8::Local<v8::StackTrace> stackTrace, size_t maxStackSize, const String16
& description) |
| 89 { | 89 { |
| 90 v8::Isolate* isolate = v8::Isolate::GetCurrent(); | 90 v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
| 91 v8::HandleScope scope(isolate); | 91 v8::HandleScope scope(isolate); |
| 92 protocol::Vector<V8StackTraceImpl::Frame> frames; | 92 protocol::Vector<V8StackTraceImpl::Frame> frames; |
| 93 if (!stackTrace.IsEmpty()) | 93 if (!stackTrace.IsEmpty()) |
| 94 toFramesVector(stackTrace, frames, maxStackSize, isolate); | 94 toFramesVector(stackTrace, frames, maxStackSize, isolate); |
| 95 | 95 |
| 96 int maxAsyncCallChainDepth = 1; | 96 int maxAsyncCallChainDepth = 1; |
| 97 V8StackTraceImpl* asyncCallChain = nullptr; | 97 V8StackTraceImpl* asyncCallChain = nullptr; |
| 98 if (agent && maxStackSize > 1) { | 98 if (agent && maxStackSize > 1) { |
| 99 asyncCallChain = agent->currentAsyncCallChain(); | 99 asyncCallChain = agent->currentAsyncCallChain(); |
| 100 maxAsyncCallChainDepth = agent->maxAsyncCallChainDepth(); | 100 maxAsyncCallChainDepth = agent->maxAsyncCallChainDepth(); |
| 101 } | 101 } |
| 102 | 102 |
| 103 // Only the top stack in the chain may be empty, so ensure that second stack
is non-empty (it's the top of appended chain). | 103 // Only the top stack in the chain may be empty, so ensure that second stack
is non-empty (it's the top of appended chain). |
| 104 if (asyncCallChain && asyncCallChain->isEmpty()) | 104 if (asyncCallChain && asyncCallChain->isEmpty()) |
| 105 asyncCallChain = asyncCallChain->m_parent.get(); | 105 asyncCallChain = asyncCallChain->m_parent.get(); |
| 106 | 106 |
| 107 if (stackTrace.IsEmpty() && !asyncCallChain) | 107 if (stackTrace.IsEmpty() && !asyncCallChain) |
| 108 return nullptr; | 108 return nullptr; |
| 109 | 109 |
| 110 OwnPtr<V8StackTraceImpl> result = adoptPtr(new V8StackTraceImpl(description,
frames, asyncCallChain ? asyncCallChain->cloneImpl() : nullptr)); | 110 std::unique_ptr<V8StackTraceImpl> result(new V8StackTraceImpl(description, f
rames, asyncCallChain ? asyncCallChain->cloneImpl() : nullptr)); |
| 111 | 111 |
| 112 // Crop to not exceed maxAsyncCallChainDepth. | 112 // Crop to not exceed maxAsyncCallChainDepth. |
| 113 V8StackTraceImpl* deepest = result.get(); | 113 V8StackTraceImpl* deepest = result.get(); |
| 114 while (deepest && maxAsyncCallChainDepth) { | 114 while (deepest && maxAsyncCallChainDepth) { |
| 115 deepest = deepest->m_parent.get(); | 115 deepest = deepest->m_parent.get(); |
| 116 maxAsyncCallChainDepth--; | 116 maxAsyncCallChainDepth--; |
| 117 } | 117 } |
| 118 if (deepest) | 118 if (deepest) |
| 119 deepest->m_parent.clear(); | 119 deepest->m_parent.reset(); |
| 120 | 120 |
| 121 return result; | 121 return result; |
| 122 } | 122 } |
| 123 | 123 |
| 124 PassOwnPtr<V8StackTraceImpl> V8StackTraceImpl::capture(V8DebuggerAgentImpl* agen
t, size_t maxStackSize, const String16& description) | 124 std::unique_ptr<V8StackTraceImpl> V8StackTraceImpl::capture(V8DebuggerAgentImpl*
agent, size_t maxStackSize, const String16& description) |
| 125 { | 125 { |
| 126 v8::Isolate* isolate = v8::Isolate::GetCurrent(); | 126 v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
| 127 v8::HandleScope handleScope(isolate); | 127 v8::HandleScope handleScope(isolate); |
| 128 v8::Local<v8::StackTrace> stackTrace; | 128 v8::Local<v8::StackTrace> stackTrace; |
| 129 if (isolate->InContext()) { | 129 if (isolate->InContext()) { |
| 130 #if V8_MAJOR_VERSION >= 5 | 130 #if V8_MAJOR_VERSION >= 5 |
| 131 isolate->GetCpuProfiler()->CollectSample(); | 131 isolate->GetCpuProfiler()->CollectSample(); |
| 132 #endif | 132 #endif |
| 133 stackTrace = v8::StackTrace::CurrentStackTrace(isolate, maxStackSize, st
ackTraceOptions); | 133 stackTrace = v8::StackTrace::CurrentStackTrace(isolate, maxStackSize, st
ackTraceOptions); |
| 134 } | 134 } |
| 135 return V8StackTraceImpl::create(agent, stackTrace, maxStackSize, description
); | 135 return V8StackTraceImpl::create(agent, stackTrace, maxStackSize, description
); |
| 136 } | 136 } |
| 137 | 137 |
| 138 PassOwnPtr<V8StackTrace> V8StackTraceImpl::clone() | 138 std::unique_ptr<V8StackTrace> V8StackTraceImpl::clone() |
| 139 { | 139 { |
| 140 OwnPtr<V8StackTraceImpl> copy = cloneImpl(); | 140 return cloneImpl(); |
| 141 return adoptPtr(static_cast<V8StackTrace*>(copy.leakPtr())); | |
| 142 } | 141 } |
| 143 | 142 |
| 144 PassOwnPtr<V8StackTraceImpl> V8StackTraceImpl::cloneImpl() | 143 std::unique_ptr<V8StackTraceImpl> V8StackTraceImpl::cloneImpl() |
| 145 { | 144 { |
| 146 protocol::Vector<Frame> framesCopy(m_frames); | 145 protocol::Vector<Frame> framesCopy(m_frames); |
| 147 return adoptPtr(new V8StackTraceImpl(m_description, framesCopy, m_parent ? m
_parent->cloneImpl() : nullptr)); | 146 return wrapUnique(new V8StackTraceImpl(m_description, framesCopy, m_parent ?
m_parent->cloneImpl() : nullptr)); |
| 148 } | 147 } |
| 149 | 148 |
| 150 V8StackTraceImpl::V8StackTraceImpl(const String16& description, protocol::Vector
<Frame>& frames, PassOwnPtr<V8StackTraceImpl> parent) | 149 V8StackTraceImpl::V8StackTraceImpl(const String16& description, protocol::Vector
<Frame>& frames, std::unique_ptr<V8StackTraceImpl> parent) |
| 151 : m_description(description) | 150 : m_description(description) |
| 152 , m_parent(std::move(parent)) | 151 , m_parent(std::move(parent)) |
| 153 { | 152 { |
| 154 m_frames.swap(frames); | 153 m_frames.swap(frames); |
| 155 } | 154 } |
| 156 | 155 |
| 157 V8StackTraceImpl::~V8StackTraceImpl() | 156 V8StackTraceImpl::~V8StackTraceImpl() |
| 158 { | 157 { |
| 159 } | 158 } |
| 160 | 159 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 181 DCHECK(m_frames.size()); | 180 DCHECK(m_frames.size()); |
| 182 return m_frames[0].m_functionName; | 181 return m_frames[0].m_functionName; |
| 183 } | 182 } |
| 184 | 183 |
| 185 String16 V8StackTraceImpl::topScriptId() const | 184 String16 V8StackTraceImpl::topScriptId() const |
| 186 { | 185 { |
| 187 DCHECK(m_frames.size()); | 186 DCHECK(m_frames.size()); |
| 188 return m_frames[0].m_scriptId; | 187 return m_frames[0].m_scriptId; |
| 189 } | 188 } |
| 190 | 189 |
| 191 PassOwnPtr<protocol::Runtime::StackTrace> V8StackTraceImpl::buildInspectorObject
() const | 190 std::unique_ptr<protocol::Runtime::StackTrace> V8StackTraceImpl::buildInspectorO
bject() const |
| 192 { | 191 { |
| 193 OwnPtr<protocol::Array<protocol::Runtime::CallFrame>> frames = protocol::Arr
ay<protocol::Runtime::CallFrame>::create(); | 192 std::unique_ptr<protocol::Array<protocol::Runtime::CallFrame>> frames = prot
ocol::Array<protocol::Runtime::CallFrame>::create(); |
| 194 for (size_t i = 0; i < m_frames.size(); i++) | 193 for (size_t i = 0; i < m_frames.size(); i++) |
| 195 frames->addItem(m_frames.at(i).buildInspectorObject()); | 194 frames->addItem(m_frames.at(i).buildInspectorObject()); |
| 196 | 195 |
| 197 OwnPtr<protocol::Runtime::StackTrace> stackTrace = protocol::Runtime::StackT
race::create() | 196 std::unique_ptr<protocol::Runtime::StackTrace> stackTrace = protocol::Runtim
e::StackTrace::create() |
| 198 .setCallFrames(std::move(frames)).build(); | 197 .setCallFrames(std::move(frames)).build(); |
| 199 if (!m_description.isEmpty()) | 198 if (!m_description.isEmpty()) |
| 200 stackTrace->setDescription(m_description); | 199 stackTrace->setDescription(m_description); |
| 201 if (m_parent) | 200 if (m_parent) |
| 202 stackTrace->setParent(m_parent->buildInspectorObject()); | 201 stackTrace->setParent(m_parent->buildInspectorObject()); |
| 203 return stackTrace; | 202 return stackTrace; |
| 204 } | 203 } |
| 205 | 204 |
| 206 PassOwnPtr<protocol::Runtime::StackTrace> V8StackTraceImpl::buildInspectorObject
ForTail(V8DebuggerAgentImpl* agent) const | 205 std::unique_ptr<protocol::Runtime::StackTrace> V8StackTraceImpl::buildInspectorO
bjectForTail(V8DebuggerAgentImpl* agent) const |
| 207 { | 206 { |
| 208 v8::HandleScope handleScope(v8::Isolate::GetCurrent()); | 207 v8::HandleScope handleScope(v8::Isolate::GetCurrent()); |
| 209 // Next call collapses possible empty stack and ensures maxAsyncCallChainDep
th. | 208 // Next call collapses possible empty stack and ensures maxAsyncCallChainDep
th. |
| 210 OwnPtr<V8StackTraceImpl> fullChain = V8StackTraceImpl::create(agent, v8::Loc
al<v8::StackTrace>(), V8StackTrace::maxCallStackSizeToCapture); | 209 std::unique_ptr<V8StackTraceImpl> fullChain = V8StackTraceImpl::create(agent
, v8::Local<v8::StackTrace>(), V8StackTrace::maxCallStackSizeToCapture); |
| 211 if (!fullChain || !fullChain->m_parent) | 210 if (!fullChain || !fullChain->m_parent) |
| 212 return nullptr; | 211 return nullptr; |
| 213 return fullChain->m_parent->buildInspectorObject(); | 212 return fullChain->m_parent->buildInspectorObject(); |
| 214 } | 213 } |
| 215 | 214 |
| 216 String16 V8StackTraceImpl::toString() const | 215 String16 V8StackTraceImpl::toString() const |
| 217 { | 216 { |
| 218 String16Builder stackTrace; | 217 String16Builder stackTrace; |
| 219 for (size_t i = 0; i < m_frames.size(); ++i) { | 218 for (size_t i = 0; i < m_frames.size(); ++i) { |
| 220 const Frame& frame = m_frames[i]; | 219 const Frame& frame = m_frames[i]; |
| 221 stackTrace.append("\n at " + (frame.functionName().length() ? frame.f
unctionName() : "(anonymous function)")); | 220 stackTrace.append("\n at " + (frame.functionName().length() ? frame.f
unctionName() : "(anonymous function)")); |
| 222 stackTrace.append(" ("); | 221 stackTrace.append(" ("); |
| 223 stackTrace.append(frame.sourceURL()); | 222 stackTrace.append(frame.sourceURL()); |
| 224 stackTrace.append(':'); | 223 stackTrace.append(':'); |
| 225 stackTrace.appendNumber(frame.lineNumber()); | 224 stackTrace.appendNumber(frame.lineNumber()); |
| 226 stackTrace.append(':'); | 225 stackTrace.append(':'); |
| 227 stackTrace.appendNumber(frame.columnNumber()); | 226 stackTrace.appendNumber(frame.columnNumber()); |
| 228 stackTrace.append(')'); | 227 stackTrace.append(')'); |
| 229 } | 228 } |
| 230 return stackTrace.toString(); | 229 return stackTrace.toString(); |
| 231 } | 230 } |
| 232 | 231 |
| 233 } // namespace blink | 232 } // namespace blink |
| OLD | NEW |