Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(47)

Side by Side Diff: src/inspector/V8StackTraceImpl.cpp

Issue 2292573002: [inspector] Initial import of v8_inspector. (Closed)
Patch Set: format the code, disable cpplint Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/inspector/V8StackTraceImpl.h ('k') | src/inspector/V8ValueCopier.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "src/inspector/V8StackTraceImpl.h"
6
7 #include "src/inspector/StringUtil.h"
8 #include "src/inspector/V8Debugger.h"
9 #include "src/inspector/protocol/Protocol.h"
10
11 #include <v8-debug.h>
12 #include <v8-profiler.h>
13 #include <v8-version.h>
14
15 namespace v8_inspector {
16
17 namespace {
18
19 static const v8::StackTrace::StackTraceOptions stackTraceOptions =
20 static_cast<v8::StackTrace::StackTraceOptions>(
21 v8::StackTrace::kLineNumber | v8::StackTrace::kColumnOffset |
22 v8::StackTrace::kScriptId | v8::StackTrace::kScriptNameOrSourceURL |
23 v8::StackTrace::kFunctionName);
24
25 V8StackTraceImpl::Frame toFrame(v8::Local<v8::StackFrame> frame) {
26 String16 scriptId = String16::fromInteger(frame->GetScriptId());
27 String16 sourceName;
28 v8::Local<v8::String> sourceNameValue(frame->GetScriptNameOrSourceURL());
29 if (!sourceNameValue.IsEmpty())
30 sourceName = toProtocolString(sourceNameValue);
31
32 String16 functionName;
33 v8::Local<v8::String> functionNameValue(frame->GetFunctionName());
34 if (!functionNameValue.IsEmpty())
35 functionName = toProtocolString(functionNameValue);
36
37 int sourceLineNumber = frame->GetLineNumber();
38 int sourceColumn = frame->GetColumn();
39 return V8StackTraceImpl::Frame(functionName, scriptId, sourceName,
40 sourceLineNumber, sourceColumn);
41 }
42
43 void toFramesVector(v8::Local<v8::StackTrace> stackTrace,
44 std::vector<V8StackTraceImpl::Frame>& frames,
45 size_t maxStackSize, v8::Isolate* isolate) {
46 DCHECK(isolate->InContext());
47 int frameCount = stackTrace->GetFrameCount();
48 if (frameCount > static_cast<int>(maxStackSize)) frameCount = maxStackSize;
49 for (int i = 0; i < frameCount; i++) {
50 v8::Local<v8::StackFrame> stackFrame = stackTrace->GetFrame(i);
51 frames.push_back(toFrame(stackFrame));
52 }
53 }
54
55 } // namespace
56
57 V8StackTraceImpl::Frame::Frame()
58 : m_functionName("undefined"),
59 m_scriptId(""),
60 m_scriptName("undefined"),
61 m_lineNumber(0),
62 m_columnNumber(0) {}
63
64 V8StackTraceImpl::Frame::Frame(const String16& functionName,
65 const String16& scriptId,
66 const String16& scriptName, int lineNumber,
67 int column)
68 : m_functionName(functionName),
69 m_scriptId(scriptId),
70 m_scriptName(scriptName),
71 m_lineNumber(lineNumber),
72 m_columnNumber(column) {
73 DCHECK(m_lineNumber != v8::Message::kNoLineNumberInfo);
74 DCHECK(m_columnNumber != v8::Message::kNoColumnInfo);
75 }
76
77 V8StackTraceImpl::Frame::~Frame() {}
78
79 // buildInspectorObject() and SourceLocation's toTracedValue() should set the
80 // same fields.
81 // If either of them is modified, the other should be also modified.
82 std::unique_ptr<protocol::Runtime::CallFrame>
83 V8StackTraceImpl::Frame::buildInspectorObject() const {
84 return protocol::Runtime::CallFrame::create()
85 .setFunctionName(m_functionName)
86 .setScriptId(m_scriptId)
87 .setUrl(m_scriptName)
88 .setLineNumber(m_lineNumber - 1)
89 .setColumnNumber(m_columnNumber - 1)
90 .build();
91 }
92
93 V8StackTraceImpl::Frame V8StackTraceImpl::Frame::clone() const {
94 return Frame(m_functionName, m_scriptId, m_scriptName, m_lineNumber,
95 m_columnNumber);
96 }
97
98 // static
99 void V8StackTraceImpl::setCaptureStackTraceForUncaughtExceptions(
100 v8::Isolate* isolate, bool capture) {
101 isolate->SetCaptureStackTraceForUncaughtExceptions(
102 capture, V8StackTraceImpl::maxCallStackSizeToCapture, stackTraceOptions);
103 }
104
105 // static
106 std::unique_ptr<V8StackTraceImpl> V8StackTraceImpl::create(
107 V8Debugger* debugger, int contextGroupId,
108 v8::Local<v8::StackTrace> stackTrace, size_t maxStackSize,
109 const String16& description) {
110 v8::Isolate* isolate = v8::Isolate::GetCurrent();
111 v8::HandleScope scope(isolate);
112 std::vector<V8StackTraceImpl::Frame> frames;
113 if (!stackTrace.IsEmpty())
114 toFramesVector(stackTrace, frames, maxStackSize, isolate);
115
116 int maxAsyncCallChainDepth = 1;
117 V8StackTraceImpl* asyncCallChain = nullptr;
118 if (debugger && maxStackSize > 1) {
119 asyncCallChain = debugger->currentAsyncCallChain();
120 maxAsyncCallChainDepth = debugger->maxAsyncCallChainDepth();
121 }
122 // Do not accidentally append async call chain from another group. This should
123 // not
124 // happen if we have proper instrumentation, but let's double-check to be
125 // safe.
126 if (contextGroupId && asyncCallChain && asyncCallChain->m_contextGroupId &&
127 asyncCallChain->m_contextGroupId != contextGroupId) {
128 asyncCallChain = nullptr;
129 maxAsyncCallChainDepth = 1;
130 }
131
132 // Only the top stack in the chain may be empty, so ensure that second stack
133 // is non-empty (it's the top of appended chain).
134 if (asyncCallChain && asyncCallChain->isEmpty())
135 asyncCallChain = asyncCallChain->m_parent.get();
136
137 if (stackTrace.IsEmpty() && !asyncCallChain) return nullptr;
138
139 std::unique_ptr<V8StackTraceImpl> result(new V8StackTraceImpl(
140 contextGroupId, description, frames,
141 asyncCallChain ? asyncCallChain->cloneImpl() : nullptr));
142
143 // Crop to not exceed maxAsyncCallChainDepth.
144 V8StackTraceImpl* deepest = result.get();
145 while (deepest && maxAsyncCallChainDepth) {
146 deepest = deepest->m_parent.get();
147 maxAsyncCallChainDepth--;
148 }
149 if (deepest) deepest->m_parent.reset();
150
151 return result;
152 }
153
154 std::unique_ptr<V8StackTraceImpl> V8StackTraceImpl::capture(
155 V8Debugger* debugger, int contextGroupId, size_t maxStackSize,
156 const String16& description) {
157 v8::Isolate* isolate = v8::Isolate::GetCurrent();
158 v8::HandleScope handleScope(isolate);
159 v8::Local<v8::StackTrace> stackTrace;
160 if (isolate->InContext()) {
161 #if V8_MAJOR_VERSION >= 5
162 isolate->GetCpuProfiler()->CollectSample();
163 #endif
164 stackTrace = v8::StackTrace::CurrentStackTrace(isolate, maxStackSize,
165 stackTraceOptions);
166 }
167 return V8StackTraceImpl::create(debugger, contextGroupId, stackTrace,
168 maxStackSize, description);
169 }
170
171 std::unique_ptr<V8StackTraceImpl> V8StackTraceImpl::cloneImpl() {
172 std::vector<Frame> framesCopy(m_frames);
173 return wrapUnique(
174 new V8StackTraceImpl(m_contextGroupId, m_description, framesCopy,
175 m_parent ? m_parent->cloneImpl() : nullptr));
176 }
177
178 std::unique_ptr<V8StackTrace> V8StackTraceImpl::clone() {
179 std::vector<Frame> frames;
180 for (size_t i = 0; i < m_frames.size(); i++)
181 frames.push_back(m_frames.at(i).clone());
182 return wrapUnique(
183 new V8StackTraceImpl(m_contextGroupId, m_description, frames, nullptr));
184 }
185
186 V8StackTraceImpl::V8StackTraceImpl(int contextGroupId,
187 const String16& description,
188 std::vector<Frame>& frames,
189 std::unique_ptr<V8StackTraceImpl> parent)
190 : m_contextGroupId(contextGroupId),
191 m_description(description),
192 m_parent(std::move(parent)) {
193 m_frames.swap(frames);
194 }
195
196 V8StackTraceImpl::~V8StackTraceImpl() {}
197
198 StringView V8StackTraceImpl::topSourceURL() const {
199 DCHECK(m_frames.size());
200 return toStringView(m_frames[0].m_scriptName);
201 }
202
203 int V8StackTraceImpl::topLineNumber() const {
204 DCHECK(m_frames.size());
205 return m_frames[0].m_lineNumber;
206 }
207
208 int V8StackTraceImpl::topColumnNumber() const {
209 DCHECK(m_frames.size());
210 return m_frames[0].m_columnNumber;
211 }
212
213 StringView V8StackTraceImpl::topFunctionName() const {
214 DCHECK(m_frames.size());
215 return toStringView(m_frames[0].m_functionName);
216 }
217
218 StringView V8StackTraceImpl::topScriptId() const {
219 DCHECK(m_frames.size());
220 return toStringView(m_frames[0].m_scriptId);
221 }
222
223 std::unique_ptr<protocol::Runtime::StackTrace>
224 V8StackTraceImpl::buildInspectorObjectImpl() const {
225 std::unique_ptr<protocol::Array<protocol::Runtime::CallFrame>> frames =
226 protocol::Array<protocol::Runtime::CallFrame>::create();
227 for (size_t i = 0; i < m_frames.size(); i++)
228 frames->addItem(m_frames.at(i).buildInspectorObject());
229
230 std::unique_ptr<protocol::Runtime::StackTrace> stackTrace =
231 protocol::Runtime::StackTrace::create()
232 .setCallFrames(std::move(frames))
233 .build();
234 if (!m_description.isEmpty()) stackTrace->setDescription(m_description);
235 if (m_parent) stackTrace->setParent(m_parent->buildInspectorObjectImpl());
236 return stackTrace;
237 }
238
239 std::unique_ptr<protocol::Runtime::StackTrace>
240 V8StackTraceImpl::buildInspectorObjectForTail(V8Debugger* debugger) const {
241 v8::HandleScope handleScope(v8::Isolate::GetCurrent());
242 // Next call collapses possible empty stack and ensures
243 // maxAsyncCallChainDepth.
244 std::unique_ptr<V8StackTraceImpl> fullChain = V8StackTraceImpl::create(
245 debugger, m_contextGroupId, v8::Local<v8::StackTrace>(),
246 V8StackTraceImpl::maxCallStackSizeToCapture);
247 if (!fullChain || !fullChain->m_parent) return nullptr;
248 return fullChain->m_parent->buildInspectorObjectImpl();
249 }
250
251 std::unique_ptr<protocol::Runtime::API::StackTrace>
252 V8StackTraceImpl::buildInspectorObject() const {
253 return buildInspectorObjectImpl();
254 }
255
256 std::unique_ptr<StringBuffer> V8StackTraceImpl::toString() const {
257 String16Builder stackTrace;
258 for (size_t i = 0; i < m_frames.size(); ++i) {
259 const Frame& frame = m_frames[i];
260 stackTrace.append("\n at " + (frame.functionName().length()
261 ? frame.functionName()
262 : "(anonymous function)"));
263 stackTrace.append(" (");
264 stackTrace.append(frame.sourceURL());
265 stackTrace.append(':');
266 stackTrace.append(String16::fromInteger(frame.lineNumber()));
267 stackTrace.append(':');
268 stackTrace.append(String16::fromInteger(frame.columnNumber()));
269 stackTrace.append(')');
270 }
271 String16 string = stackTrace.toString();
272 return StringBufferImpl::adopt(string);
273 }
274
275 } // namespace v8_inspector
OLDNEW
« no previous file with comments | « src/inspector/V8StackTraceImpl.h ('k') | src/inspector/V8ValueCopier.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698