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

Side by Side Diff: observatory_pub_packages/stack_trace/src/frame.dart

Issue 816693004: Add observatory_pub_packages snapshot to third_party (Closed) Base URL: http://dart.googlecode.com/svn/third_party/
Patch Set: Created 6 years 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 library frame;
6
7
8 import 'package:path/path.dart' as path;
9
10 import 'trace.dart';
11
12 // #1 Foo._bar (file:///home/nweiz/code/stuff.dart:42:21)
13 final _vmFrame = new RegExp(
14 r'^#\d+\s+(\S.*) \((.+?):(\d+)(?::(\d+))?\)$');
15
16 // at VW.call$0 (http://pub.dartlang.org/stuff.dart.js:560:28)
17 // at VW.call$0 (eval as fn
18 // (http://pub.dartlang.org/stuff.dart.js:560:28), efn:3:28)
19 // at http://pub.dartlang.org/stuff.dart.js:560:28
20 final _v8Frame = new RegExp(
21 r'^\s*at (?:(\S.*?)(?: \[as [^\]]+\])? \((.*)\)|(.*))$');
22
23 // http://pub.dartlang.org/stuff.dart.js:560:28
24 final _v8UrlLocation = new RegExp(r'^(.*):(\d+):(\d+)$');
25
26 // eval as function (http://pub.dartlang.org/stuff.dart.js:560:28), efn:3:28
27 // eval as function (http://pub.dartlang.org/stuff.dart.js:560:28)
28 // eval as function (eval as otherFunction
29 // (http://pub.dartlang.org/stuff.dart.js:560:28))
30 final _v8EvalLocation = new RegExp(
31 r'^eval at (?:\S.*?) \((.*)\)(?:, .*?:\d+:\d+)?$');
32
33 // .VW.call$0@http://pub.dartlang.org/stuff.dart.js:560
34 // .VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560
35 // .VW.call$0/name<@http://pub.dartlang.org/stuff.dart.js:560
36 // .VW.call$0@http://pub.dartlang.org/stuff.dart.js:560:36
37 // http://pub.dartlang.org/stuff.dart.js:560
38 final _firefoxSafariFrame = new RegExp(
39 r'^'
40 r'(?:' // Member description. Not present in some Safari frames.
41 r'([^@(/]*)' // The actual name of the member.
42 r'(?:\(.*\))?' // Arguments to the member, sometimes captured by Firefox.
43 r'((?:/[^/]*)*)' // Extra characters indicating a nested closure.
44 r'(?:\(.*\))?' // Arguments to the closure.
45 r'@'
46 r')?'
47 r'(.*?)' // The frame's URL.
48 r':'
49 r'(\d*)' // The line number. Empty in Safari if it's unknown.
50 r'(?::(\d*))?' // The column number. Not present in older browsers and
51 // empty in Safari if it's unknown.
52 r'$');
53
54 // foo/bar.dart 10:11 in Foo._bar
55 // http://dartlang.org/foo/bar.dart in Foo._bar
56 final _friendlyFrame = new RegExp(
57 r'^(\S+)(?: (\d+)(?::(\d+))?)?\s+([^\d]\S*)$');
58
59 final _initialDot = new RegExp(r"^\.");
60
61 /// A single stack frame. Each frame points to a precise location in Dart code.
62 class Frame {
63 /// The URI of the file in which the code is located.
64 ///
65 /// This URI will usually have the scheme `dart`, `file`, `http`, or `https`.
66 final Uri uri;
67
68 /// The line number on which the code location is located.
69 ///
70 /// This can be null, indicating that the line number is unknown or
71 /// unimportant.
72 final int line;
73
74 /// The column number of the code location.
75 ///
76 /// This can be null, indicating that the column number is unknown or
77 /// unimportant.
78 final int column;
79
80 /// The name of the member in which the code location occurs.
81 ///
82 /// Anonymous closures are represented as `<fn>` in this member string.
83 final String member;
84
85 /// Whether this stack frame comes from the Dart core libraries.
86 bool get isCore => uri.scheme == 'dart';
87
88 /// Returns a human-friendly description of the library that this stack frame
89 /// comes from.
90 ///
91 /// This will usually be the string form of [uri], but a relative URI will be
92 /// used if possible.
93 String get library => path.prettyUri(uri);
94
95 /// Returns the name of the package this stack frame comes from, or `null` if
96 /// this stack frame doesn't come from a `package:` URL.
97 String get package {
98 if (uri.scheme != 'package') return null;
99 return uri.path.split('/').first;
100 }
101
102 /// A human-friendly description of the code location.
103 String get location {
104 if (line == null) return library;
105 if (column == null) return '$library $line';
106 return '$library $line:$column';
107 }
108
109 /// Returns a single frame of the current stack.
110 ///
111 /// By default, this will return the frame above the current method. If
112 /// [level] is `0`, it will return the current method's frame; if [level] is
113 /// higher than `1`, it will return higher frames.
114 factory Frame.caller([int level=1]) {
115 if (level < 0) {
116 throw new ArgumentError("Argument [level] must be greater than or equal "
117 "to 0.");
118 }
119
120 return new Trace.current(level + 1).frames.first;
121 }
122
123 /// Parses a string representation of a Dart VM stack frame.
124 factory Frame.parseVM(String frame) {
125 // The VM sometimes folds multiple stack frames together and replaces them
126 // with "...".
127 if (frame == '...') {
128 return new Frame(new Uri(), null, null, '...');
129 }
130
131 var match = _vmFrame.firstMatch(frame);
132 if (match == null) {
133 throw new FormatException("Couldn't parse VM stack trace line '$frame'.");
134 }
135
136 // Get the pieces out of the regexp match. Function, URI and line should
137 // always be found. The column is optional.
138 var member = match[1].replaceAll("<anonymous closure>", "<fn>");
139 var uri = Uri.parse(match[2]);
140 var line = int.parse(match[3]);
141 var column = null;
142 var columnMatch = match[4];
143 if (columnMatch != null) {
144 column = int.parse(columnMatch);
145 }
146 return new Frame(uri, line, column, member);
147 }
148
149 /// Parses a string representation of a Chrome/V8 stack frame.
150 factory Frame.parseV8(String frame) {
151 var match = _v8Frame.firstMatch(frame);
152 if (match == null) {
153 throw new FormatException("Couldn't parse V8 stack trace line '$frame'.");
154 }
155
156 // v8 location strings can be arbitrarily-nested, since it adds a layer of
157 // nesting for each eval performed on that line.
158 parseLocation(location, member) {
159 var evalMatch = _v8EvalLocation.firstMatch(location);
160 while (evalMatch != null) {
161 location = evalMatch[1];
162 evalMatch = _v8EvalLocation.firstMatch(location);
163 }
164
165 var urlMatch = _v8UrlLocation.firstMatch(location);
166 if (urlMatch == null) {
167 throw new FormatException(
168 "Couldn't parse V8 stack trace line '$frame'.");
169 }
170
171 return new Frame(
172 _uriOrPathToUri(urlMatch[1]),
173 int.parse(urlMatch[2]),
174 int.parse(urlMatch[3]),
175 member);
176 }
177
178 // V8 stack frames can be in two forms.
179 if (match[2] != null) {
180 // The first form looks like " at FUNCTION (LOCATION)". V8 proper lists
181 // anonymous functions within eval as "<anonymous>", while IE10 lists them
182 // as "Anonymous function".
183 return parseLocation(match[2],
184 match[1].replaceAll("<anonymous>", "<fn>")
185 .replaceAll("Anonymous function", "<fn>"));
186 } else {
187 // The second form looks like " at LOCATION", and is used for anonymous
188 // functions.
189 return parseLocation(match[3], "<fn>");
190 }
191 }
192
193 /// Parses a string representation of an IE stack frame.
194 ///
195 /// IE10+ frames look just like V8 frames. Prior to IE10, stack traces can't
196 /// be retrieved.
197 factory Frame.parseIE(String frame) => new Frame.parseV8(frame);
198
199 /// Parses a string representation of a Firefox stack frame.
200 factory Frame.parseFirefox(String frame) {
201 var match = _firefoxSafariFrame.firstMatch(frame);
202 if (match == null) {
203 throw new FormatException(
204 "Couldn't parse Firefox/Safari stack trace line '$frame'.");
205 }
206
207 // Normally this is a URI, but in a jsshell trace it can be a path.
208 var uri = _uriOrPathToUri(match[3]);
209
210 var member;
211 if (match[1] != null) {
212 member = match[1];
213 member +=
214 new List.filled('/'.allMatches(match[2]).length, ".<fn>").join();
215 if (member == '') member = '<fn>';
216
217 // Some Firefox members have initial dots. We remove them for consistency
218 // with other platforms.
219 member = member.replaceFirst(_initialDot, '');
220 } else {
221 member = '<fn>';
222 }
223
224 var line = match[4] == '' ? null : int.parse(match[4]);
225 var column = match[5] == null || match[5] == '' ?
226 null : int.parse(match[5]);
227 return new Frame(uri, line, column, member);
228 }
229
230 /// Parses a string representation of a Safari 6.0 stack frame.
231 @Deprecated("Use Frame.parseSafari instead.")
232 factory Frame.parseSafari6_0(String frame) => new Frame.parseFirefox(frame);
233
234 /// Parses a string representation of a Safari 6.1+ stack frame.
235 @Deprecated("Use Frame.parseSafari instead.")
236 factory Frame.parseSafari6_1(String frame) => new Frame.parseFirefox(frame);
237
238 /// Parses a string representation of a Safari stack frame.
239 factory Frame.parseSafari(String frame) => new Frame.parseFirefox(frame);
240
241 /// Parses this package's string representation of a stack frame.
242 factory Frame.parseFriendly(String frame) {
243 var match = _friendlyFrame.firstMatch(frame);
244 if (match == null) {
245 throw new FormatException(
246 "Couldn't parse package:stack_trace stack trace line '$frame'.");
247 }
248
249 var uri = Uri.parse(match[1]);
250 // If there's no scheme, this is a relative URI. We should interpret it as
251 // relative to the current working directory.
252 if (uri.scheme == '') {
253 uri = path.toUri(path.absolute(path.fromUri(uri)));
254 }
255
256 var line = match[2] == null ? null : int.parse(match[2]);
257 var column = match[3] == null ? null : int.parse(match[3]);
258 return new Frame(uri, line, column, match[4]);
259 }
260
261 /// A regular expression matching an absolute URI.
262 static final _uriRegExp = new RegExp(r'^[a-zA-Z][-+.a-zA-Z\d]*://');
263
264 /// A regular expression matching a Windows path.
265 static final _windowsRegExp = new RegExp(r'^([a-zA-Z]:[\\/]|\\\\)');
266
267 /// Converts [uriOrPath], which can be a URI, a Windows path, or a Posix path,
268 /// to a URI (absolute if possible).
269 static Uri _uriOrPathToUri(String uriOrPath) {
270 if (uriOrPath.contains(_uriRegExp)) {
271 return Uri.parse(uriOrPath);
272 } else if (uriOrPath.contains(_windowsRegExp)) {
273 return new Uri.file(uriOrPath, windows: true);
274 } else if (uriOrPath.startsWith('/')) {
275 return new Uri.file(uriOrPath, windows: false);
276 }
277
278 // As far as I've seen, Firefox and V8 both always report absolute paths in
279 // their stack frames. However, if we do get a relative path, we should
280 // handle it gracefully.
281 if (uriOrPath.contains('\\')) return path.windows.toUri(uriOrPath);
282 return Uri.parse(uriOrPath);
283 }
284
285 Frame(this.uri, this.line, this.column, this.member);
286
287 String toString() => '$location in $member';
288 }
OLDNEW
« no previous file with comments | « observatory_pub_packages/stack_trace/src/chain.dart ('k') | observatory_pub_packages/stack_trace/src/lazy_trace.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698