| 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/v8_inspector/V8DebuggerAgentImpl.h" | 8 #include "platform/v8_inspector/V8DebuggerAgentImpl.h" |
| 8 #include "platform/v8_inspector/V8DebuggerImpl.h" | 9 #include "platform/v8_inspector/V8DebuggerImpl.h" |
| 9 #include "platform/v8_inspector/V8StringUtil.h" | 10 #include "platform/v8_inspector/V8StringUtil.h" |
| 10 #include "wtf/PassOwnPtr.h" | 11 #include "wtf/PassOwnPtr.h" |
| 11 #include "wtf/text/StringBuilder.h" | |
| 12 | 12 |
| 13 #include <v8-debug.h> | 13 #include <v8-debug.h> |
| 14 #include <v8-profiler.h> | 14 #include <v8-profiler.h> |
| 15 | 15 |
| 16 namespace blink { | 16 namespace blink { |
| 17 | 17 |
| 18 namespace { | 18 namespace { |
| 19 | 19 |
| 20 V8StackTraceImpl::Frame toCallFrame(v8::Local<v8::StackFrame> frame) | 20 V8StackTraceImpl::Frame toCallFrame(v8::Local<v8::StackFrame> frame) |
| 21 { | 21 { |
| 22 String scriptId = String::number(frame->GetScriptId()); | 22 String16 scriptId = String16::number(frame->GetScriptId()); |
| 23 String sourceName; | 23 String16 sourceName; |
| 24 v8::Local<v8::String> sourceNameValue(frame->GetScriptNameOrSourceURL()); | 24 v8::Local<v8::String> sourceNameValue(frame->GetScriptNameOrSourceURL()); |
| 25 if (!sourceNameValue.IsEmpty()) | 25 if (!sourceNameValue.IsEmpty()) |
| 26 sourceName = toWTFString(sourceNameValue); | 26 sourceName = toProtocolString(sourceNameValue); |
| 27 | 27 |
| 28 String functionName; | 28 String16 functionName; |
| 29 v8::Local<v8::String> functionNameValue(frame->GetFunctionName()); | 29 v8::Local<v8::String> functionNameValue(frame->GetFunctionName()); |
| 30 if (!functionNameValue.IsEmpty()) | 30 if (!functionNameValue.IsEmpty()) |
| 31 functionName = toWTFString(functionNameValue); | 31 functionName = toProtocolString(functionNameValue); |
| 32 | 32 |
| 33 int sourceLineNumber = frame->GetLineNumber(); | 33 int sourceLineNumber = frame->GetLineNumber(); |
| 34 int sourceColumn = frame->GetColumn(); | 34 int sourceColumn = frame->GetColumn(); |
| 35 return V8StackTraceImpl::Frame(functionName, scriptId, sourceName, sourceLin
eNumber, sourceColumn); | 35 return V8StackTraceImpl::Frame(functionName, scriptId, sourceName, sourceLin
eNumber, sourceColumn); |
| 36 } | 36 } |
| 37 | 37 |
| 38 void toCallFramesVector(v8::Local<v8::StackTrace> stackTrace, protocol::Vector<V
8StackTraceImpl::Frame>& scriptCallFrames, size_t maxStackSize, v8::Isolate* iso
late) | 38 void toCallFramesVector(v8::Local<v8::StackTrace> stackTrace, protocol::Vector<V
8StackTraceImpl::Frame>& scriptCallFrames, size_t maxStackSize, v8::Isolate* iso
late) |
| 39 { | 39 { |
| 40 ASSERT(isolate->InContext()); | 40 ASSERT(isolate->InContext()); |
| 41 int frameCount = stackTrace->GetFrameCount(); | 41 int frameCount = stackTrace->GetFrameCount(); |
| 42 if (frameCount > static_cast<int>(maxStackSize)) | 42 if (frameCount > static_cast<int>(maxStackSize)) |
| 43 frameCount = maxStackSize; | 43 frameCount = maxStackSize; |
| 44 for (int i = 0; i < frameCount; i++) { | 44 for (int i = 0; i < frameCount; i++) { |
| 45 v8::Local<v8::StackFrame> stackFrame = stackTrace->GetFrame(i); | 45 v8::Local<v8::StackFrame> stackFrame = stackTrace->GetFrame(i); |
| 46 scriptCallFrames.append(toCallFrame(stackFrame)); | 46 scriptCallFrames.append(toCallFrame(stackFrame)); |
| 47 } | 47 } |
| 48 } | 48 } |
| 49 | 49 |
| 50 } // namespace | 50 } // namespace |
| 51 | 51 |
| 52 V8StackTraceImpl::Frame::Frame() | 52 V8StackTraceImpl::Frame::Frame() |
| 53 : m_functionName("undefined") | 53 : m_functionName("undefined") |
| 54 , m_scriptId("") | 54 , m_scriptId("") |
| 55 , m_scriptName("undefined") | 55 , m_scriptName("undefined") |
| 56 , m_lineNumber(0) | 56 , m_lineNumber(0) |
| 57 , m_columnNumber(0) | 57 , m_columnNumber(0) |
| 58 { | 58 { |
| 59 } | 59 } |
| 60 | 60 |
| 61 V8StackTraceImpl::Frame::Frame(const String& functionName, const String& scriptI
d, const String& scriptName, int lineNumber, int column) | 61 V8StackTraceImpl::Frame::Frame(const String16& functionName, const String16& scr
iptId, const String16& scriptName, int lineNumber, int column) |
| 62 : m_functionName(functionName) | 62 : m_functionName(functionName) |
| 63 , m_scriptId(scriptId) | 63 , m_scriptId(scriptId) |
| 64 , m_scriptName(scriptName) | 64 , m_scriptName(scriptName) |
| 65 , m_lineNumber(lineNumber) | 65 , m_lineNumber(lineNumber) |
| 66 , m_columnNumber(column) | 66 , m_columnNumber(column) |
| 67 { | 67 { |
| 68 } | 68 } |
| 69 | 69 |
| 70 V8StackTraceImpl::Frame::~Frame() | 70 V8StackTraceImpl::Frame::~Frame() |
| 71 { | 71 { |
| 72 } | 72 } |
| 73 | 73 |
| 74 // buildInspectorObject() and ScriptCallStack's toTracedValue() should set the s
ame fields. | 74 // buildInspectorObject() and ScriptCallStack's toTracedValue() should set the s
ame fields. |
| 75 // If either of them is modified, the other should be also modified. | 75 // If either of them is modified, the other should be also modified. |
| 76 PassOwnPtr<protocol::Runtime::CallFrame> V8StackTraceImpl::Frame::buildInspector
Object() const | 76 PassOwnPtr<protocol::Runtime::CallFrame> V8StackTraceImpl::Frame::buildInspector
Object() const |
| 77 { | 77 { |
| 78 return protocol::Runtime::CallFrame::create() | 78 return protocol::Runtime::CallFrame::create() |
| 79 .setFunctionName(m_functionName) | 79 .setFunctionName(m_functionName) |
| 80 .setScriptId(m_scriptId) | 80 .setScriptId(m_scriptId) |
| 81 .setUrl(m_scriptName) | 81 .setUrl(m_scriptName) |
| 82 .setLineNumber(m_lineNumber) | 82 .setLineNumber(m_lineNumber) |
| 83 .setColumnNumber(m_columnNumber) | 83 .setColumnNumber(m_columnNumber) |
| 84 .build(); | 84 .build(); |
| 85 } | 85 } |
| 86 | 86 |
| 87 PassOwnPtr<V8StackTraceImpl> V8StackTraceImpl::create(V8DebuggerAgentImpl* agent
, v8::Local<v8::StackTrace> stackTrace, size_t maxStackSize, const String& descr
iption) | 87 PassOwnPtr<V8StackTraceImpl> V8StackTraceImpl::create(V8DebuggerAgentImpl* agent
, v8::Local<v8::StackTrace> stackTrace, size_t maxStackSize, const String16& des
cription) |
| 88 { | 88 { |
| 89 v8::Isolate* isolate = v8::Isolate::GetCurrent(); | 89 v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
| 90 v8::HandleScope scope(isolate); | 90 v8::HandleScope scope(isolate); |
| 91 protocol::Vector<V8StackTraceImpl::Frame> scriptCallFrames; | 91 protocol::Vector<V8StackTraceImpl::Frame> scriptCallFrames; |
| 92 if (!stackTrace.IsEmpty()) | 92 if (!stackTrace.IsEmpty()) |
| 93 toCallFramesVector(stackTrace, scriptCallFrames, maxStackSize, isolate); | 93 toCallFramesVector(stackTrace, scriptCallFrames, maxStackSize, isolate); |
| 94 | 94 |
| 95 OwnPtr<V8StackTraceImpl> asyncCallStack; | 95 OwnPtr<V8StackTraceImpl> asyncCallStack; |
| 96 if (agent && agent->trackingAsyncCalls() && maxStackSize > 1) | 96 if (agent && agent->trackingAsyncCalls() && maxStackSize > 1) |
| 97 asyncCallStack = agent->currentAsyncStackTraceForRuntime(); | 97 asyncCallStack = agent->currentAsyncStackTraceForRuntime(); |
| 98 | 98 |
| 99 if (stackTrace.IsEmpty() && !asyncCallStack) | 99 if (stackTrace.IsEmpty() && !asyncCallStack) |
| 100 return nullptr; | 100 return nullptr; |
| 101 | 101 |
| 102 return V8StackTraceImpl::create(description, scriptCallFrames, asyncCallStac
k.release()); | 102 return V8StackTraceImpl::create(description, scriptCallFrames, asyncCallStac
k.release()); |
| 103 } | 103 } |
| 104 | 104 |
| 105 PassOwnPtr<V8StackTraceImpl> V8StackTraceImpl::capture(V8DebuggerAgentImpl* agen
t, size_t maxStackSize, const String& description) | 105 PassOwnPtr<V8StackTraceImpl> V8StackTraceImpl::capture(V8DebuggerAgentImpl* agen
t, size_t maxStackSize, const String16& description) |
| 106 { | 106 { |
| 107 v8::Isolate* isolate = v8::Isolate::GetCurrent(); | 107 v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
| 108 v8::HandleScope handleScope(isolate); | 108 v8::HandleScope handleScope(isolate); |
| 109 v8::Local<v8::StackTrace> stackTrace; | 109 v8::Local<v8::StackTrace> stackTrace; |
| 110 if (isolate->InContext()) { | 110 if (isolate->InContext()) { |
| 111 isolate->GetCpuProfiler()->CollectSample(); | 111 isolate->GetCpuProfiler()->CollectSample(); |
| 112 stackTrace = v8::StackTrace::CurrentStackTrace(isolate, maxStackSize, st
ackTraceOptions); | 112 stackTrace = v8::StackTrace::CurrentStackTrace(isolate, maxStackSize, st
ackTraceOptions); |
| 113 } | 113 } |
| 114 return V8StackTraceImpl::create(agent, stackTrace, maxStackSize, description
); | 114 return V8StackTraceImpl::create(agent, stackTrace, maxStackSize, description
); |
| 115 } | 115 } |
| 116 | 116 |
| 117 PassOwnPtr<V8StackTraceImpl> V8StackTraceImpl::create(const String& description,
protocol::Vector<Frame>& frames, PassOwnPtr<V8StackTraceImpl> parent) | 117 PassOwnPtr<V8StackTraceImpl> V8StackTraceImpl::create(const String16& descriptio
n, protocol::Vector<Frame>& frames, PassOwnPtr<V8StackTraceImpl> parent) |
| 118 { | 118 { |
| 119 return adoptPtr(new V8StackTraceImpl(description, frames, parent)); | 119 return adoptPtr(new V8StackTraceImpl(description, frames, parent)); |
| 120 } | 120 } |
| 121 | 121 |
| 122 PassOwnPtr<V8StackTraceImpl> V8StackTraceImpl::clone(V8StackTraceImpl* origin, s
ize_t maxStackSize) | 122 PassOwnPtr<V8StackTraceImpl> V8StackTraceImpl::clone(V8StackTraceImpl* origin, s
ize_t maxStackSize) |
| 123 { | 123 { |
| 124 if (!origin) | 124 if (!origin) |
| 125 return nullptr; | 125 return nullptr; |
| 126 | 126 |
| 127 // TODO(dgozman): move this check to call-site. | 127 // TODO(dgozman): move this check to call-site. |
| 128 if (!origin->m_frames.size()) | 128 if (!origin->m_frames.size()) |
| 129 return V8StackTraceImpl::clone(origin->m_parent.get(), maxStackSize); | 129 return V8StackTraceImpl::clone(origin->m_parent.get(), maxStackSize); |
| 130 | 130 |
| 131 OwnPtr<V8StackTraceImpl> parent; | 131 OwnPtr<V8StackTraceImpl> parent; |
| 132 if (origin->m_parent && maxStackSize) | 132 if (origin->m_parent && maxStackSize) |
| 133 parent = V8StackTraceImpl::clone(origin->m_parent.get(), maxStackSize -
1); | 133 parent = V8StackTraceImpl::clone(origin->m_parent.get(), maxStackSize -
1); |
| 134 | 134 |
| 135 protocol::Vector<Frame> frames(origin->m_frames); | 135 protocol::Vector<Frame> frames(origin->m_frames); |
| 136 return adoptPtr(new V8StackTraceImpl(origin->m_description, frames, parent.r
elease())); | 136 return adoptPtr(new V8StackTraceImpl(origin->m_description, frames, parent.r
elease())); |
| 137 } | 137 } |
| 138 | 138 |
| 139 V8StackTraceImpl::V8StackTraceImpl(const String& description, protocol::Vector<F
rame>& frames, PassOwnPtr<V8StackTraceImpl> parent) | 139 V8StackTraceImpl::V8StackTraceImpl(const String16& description, protocol::Vector
<Frame>& frames, PassOwnPtr<V8StackTraceImpl> parent) |
| 140 : m_description(description) | 140 : m_description(description) |
| 141 , m_parent(parent) | 141 , m_parent(parent) |
| 142 { | 142 { |
| 143 m_frames.swap(frames); | 143 m_frames.swap(frames); |
| 144 } | 144 } |
| 145 | 145 |
| 146 V8StackTraceImpl::~V8StackTraceImpl() | 146 V8StackTraceImpl::~V8StackTraceImpl() |
| 147 { | 147 { |
| 148 } | 148 } |
| 149 | 149 |
| 150 String V8StackTraceImpl::topSourceURL() const | 150 String16 V8StackTraceImpl::topSourceURL() const |
| 151 { | 151 { |
| 152 ASSERT(m_frames.size()); | 152 ASSERT(m_frames.size()); |
| 153 return m_frames[0].m_scriptName; | 153 return m_frames[0].m_scriptName; |
| 154 } | 154 } |
| 155 | 155 |
| 156 int V8StackTraceImpl::topLineNumber() const | 156 int V8StackTraceImpl::topLineNumber() const |
| 157 { | 157 { |
| 158 ASSERT(m_frames.size()); | 158 ASSERT(m_frames.size()); |
| 159 return m_frames[0].m_lineNumber; | 159 return m_frames[0].m_lineNumber; |
| 160 } | 160 } |
| 161 | 161 |
| 162 int V8StackTraceImpl::topColumnNumber() const | 162 int V8StackTraceImpl::topColumnNumber() const |
| 163 { | 163 { |
| 164 ASSERT(m_frames.size()); | 164 ASSERT(m_frames.size()); |
| 165 return m_frames[0].m_columnNumber; | 165 return m_frames[0].m_columnNumber; |
| 166 } | 166 } |
| 167 | 167 |
| 168 String V8StackTraceImpl::topFunctionName() const | 168 String16 V8StackTraceImpl::topFunctionName() const |
| 169 { | 169 { |
| 170 ASSERT(m_frames.size()); | 170 ASSERT(m_frames.size()); |
| 171 return m_frames[0].m_functionName; | 171 return m_frames[0].m_functionName; |
| 172 } | 172 } |
| 173 | 173 |
| 174 String V8StackTraceImpl::topScriptId() const | 174 String16 V8StackTraceImpl::topScriptId() const |
| 175 { | 175 { |
| 176 ASSERT(m_frames.size()); | 176 ASSERT(m_frames.size()); |
| 177 return m_frames[0].m_scriptId; | 177 return m_frames[0].m_scriptId; |
| 178 } | 178 } |
| 179 | 179 |
| 180 PassOwnPtr<protocol::Runtime::StackTrace> V8StackTraceImpl::buildInspectorObject
() const | 180 PassOwnPtr<protocol::Runtime::StackTrace> V8StackTraceImpl::buildInspectorObject
() const |
| 181 { | 181 { |
| 182 OwnPtr<protocol::Array<protocol::Runtime::CallFrame>> frames = protocol::Arr
ay<protocol::Runtime::CallFrame>::create(); | 182 OwnPtr<protocol::Array<protocol::Runtime::CallFrame>> frames = protocol::Arr
ay<protocol::Runtime::CallFrame>::create(); |
| 183 for (size_t i = 0; i < m_frames.size(); i++) | 183 for (size_t i = 0; i < m_frames.size(); i++) |
| 184 frames->addItem(m_frames.at(i).buildInspectorObject()); | 184 frames->addItem(m_frames.at(i).buildInspectorObject()); |
| 185 | 185 |
| 186 OwnPtr<protocol::Runtime::StackTrace> stackTrace = protocol::Runtime::StackT
race::create() | 186 OwnPtr<protocol::Runtime::StackTrace> stackTrace = protocol::Runtime::StackT
race::create() |
| 187 .setCallFrames(frames.release()).build(); | 187 .setCallFrames(frames.release()).build(); |
| 188 if (!m_description.isEmpty()) | 188 if (!m_description.isEmpty()) |
| 189 stackTrace->setDescription(m_description); | 189 stackTrace->setDescription(m_description); |
| 190 if (m_parent) | 190 if (m_parent) |
| 191 stackTrace->setParent(m_parent->buildInspectorObject()); | 191 stackTrace->setParent(m_parent->buildInspectorObject()); |
| 192 return stackTrace.release(); | 192 return stackTrace.release(); |
| 193 } | 193 } |
| 194 | 194 |
| 195 String V8StackTraceImpl::toString() const | 195 String16 V8StackTraceImpl::toString() const |
| 196 { | 196 { |
| 197 StringBuilder stackTrace; | 197 String16Builder stackTrace; |
| 198 for (size_t i = 0; i < m_frames.size(); ++i) { | 198 for (size_t i = 0; i < m_frames.size(); ++i) { |
| 199 const Frame& frame = m_frames[i]; | 199 const Frame& frame = m_frames[i]; |
| 200 stackTrace.append("\n at " + (frame.functionName().length() ? frame.f
unctionName() : "(anonymous function)")); | 200 stackTrace.append("\n at " + (frame.functionName().length() ? frame.f
unctionName() : "(anonymous function)")); |
| 201 stackTrace.appendLiteral(" ("); | 201 stackTrace.append(" ("); |
| 202 stackTrace.append(frame.sourceURL()); | 202 stackTrace.append(frame.sourceURL()); |
| 203 stackTrace.append(':'); | 203 stackTrace.append(':'); |
| 204 stackTrace.appendNumber(frame.lineNumber()); | 204 stackTrace.appendNumber(frame.lineNumber()); |
| 205 stackTrace.append(':'); | 205 stackTrace.append(':'); |
| 206 stackTrace.appendNumber(frame.columnNumber()); | 206 stackTrace.appendNumber(frame.columnNumber()); |
| 207 stackTrace.append(')'); | 207 stackTrace.append(')'); |
| 208 } | 208 } |
| 209 return stackTrace.toString(); | 209 return stackTrace.toString(); |
| 210 } | 210 } |
| 211 | 211 |
| 212 } // namespace blink | 212 } // namespace blink |
| OLD | NEW |