Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library frame; | 5 library frame; |
| 6 | 6 |
| 7 | 7 |
| 8 import 'package:path/path.dart' as path; | 8 import 'package:path/path.dart' as path; |
| 9 | 9 |
| 10 import 'trace.dart'; | 10 import 'trace.dart'; |
| 11 | 11 |
| 12 // #1 Foo._bar (file:///home/nweiz/code/stuff.dart:42:21) | 12 // #1 Foo._bar (file:///home/nweiz/code/stuff.dart:42:21) |
| 13 final _vmFrame = new RegExp( | 13 final _vmFrame = new RegExp( |
| 14 r'^#\d+\s+([^\s].*) \((.+?):(\d+)(?::(\d+))?\)$'); | 14 r'^#\d+\s+([^\s].*) \((.+?):(\d+)(?::(\d+))?\)$'); |
| 15 | 15 |
| 16 // at VW.call$0 (http://pub.dartlang.org/stuff.dart.js:560:28) | 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) | |
| 17 // at http://pub.dartlang.org/stuff.dart.js:560:28 | 19 // at http://pub.dartlang.org/stuff.dart.js:560:28 |
| 18 final _v8Frame = new RegExp( | 20 final _v8Frame = new RegExp( |
| 19 r'^\s*at (?:([^\s].*?)(?: \[as [^\]]+\])? ' | 21 r'^\s*at (?:([^\s].*?)(?: \[as [^\]]+\])? \((.*)\)|(.*))$'); |
|
Bob Nystrom
2014/01/09 17:22:00
You can use "\S" instead of "[^\s]", I think. Here
nweiz
2014/01/09 21:12:35
Done.
| |
| 20 r'\((.+):(\d+):(\d+)\)|(.+):(\d+):(\d+))$'); | |
| 21 | 22 |
| 22 /// foo$bar$0@http://pub.dartlang.org/stuff.dart.js:560:28 | 23 // http://pub.dartlang.org/stuff.dart.js:560:28 |
| 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 // foo$bar$0@http://pub.dartlang.org/stuff.dart.js:560:28 | |
| 34 // http://pub.dartlang.org/stuff.dart.js:560:28 | |
| 24 final _safariFrame = new RegExp(r"^(?:([0-9A-Za-z_$]*)@)?(.*):(\d*):(\d*)$"); | 35 final _safariFrame = new RegExp(r"^(?:([0-9A-Za-z_$]*)@)?(.*):(\d*):(\d*)$"); |
| 25 | 36 |
| 26 // .VW.call$0@http://pub.dartlang.org/stuff.dart.js:560 | 37 // .VW.call$0@http://pub.dartlang.org/stuff.dart.js:560 |
| 27 // .VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560 | 38 // .VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560 |
| 28 // .VW.call$0/name<@http://pub.dartlang.org/stuff.dart.js:560 | 39 // .VW.call$0/name<@http://pub.dartlang.org/stuff.dart.js:560 |
| 29 final _firefoxFrame = new RegExp( | 40 final _firefoxFrame = new RegExp( |
| 30 r'^([^@(/]*)(?:\(.*\))?((?:/[^/]*)*)(?:\(.*\))?@(.*):(\d+)$'); | 41 r'^([^@(/]*)(?:\(.*\))?((?:/[^/]*)*)(?:\(.*\))?@(.*):(\d+)$'); |
| 31 | 42 |
| 32 // foo/bar.dart 10:11 in Foo._bar | 43 // foo/bar.dart 10:11 in Foo._bar |
| 33 // http://dartlang.org/foo/bar.dart in Foo._bar | 44 // http://dartlang.org/foo/bar.dart in Foo._bar |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 132 return new Frame(uri, line, column, member); | 143 return new Frame(uri, line, column, member); |
| 133 } | 144 } |
| 134 | 145 |
| 135 /// Parses a string representation of a Chrome/V8 stack frame. | 146 /// Parses a string representation of a Chrome/V8 stack frame. |
| 136 factory Frame.parseV8(String frame) { | 147 factory Frame.parseV8(String frame) { |
| 137 var match = _v8Frame.firstMatch(frame); | 148 var match = _v8Frame.firstMatch(frame); |
| 138 if (match == null) { | 149 if (match == null) { |
| 139 throw new FormatException("Couldn't parse V8 stack trace line '$frame'."); | 150 throw new FormatException("Couldn't parse V8 stack trace line '$frame'."); |
| 140 } | 151 } |
| 141 | 152 |
| 153 // v8 location strings can be arbitrarily-nested, since it adds a layer of | |
| 154 // nesting for each eval performed on that line. | |
| 155 parseLocation(location, member) { | |
| 156 var evalMatch = _v8EvalLocation.firstMatch(location); | |
| 157 if (evalMatch != null) return parseLocation(evalMatch[1], member); | |
|
Bob Nystrom
2014/01/09 17:22:00
I'd prefer iteration over recursion here.
nweiz
2014/01/09 21:12:35
Done.
| |
| 158 | |
| 159 | |
| 160 var urlMatch = _v8UrlLocation.firstMatch(location); | |
| 161 if (urlMatch == null) { | |
| 162 throw new FormatException( | |
| 163 "Couldn't parse V8 stack trace line '$frame'."); | |
| 164 } | |
| 165 | |
| 166 return new Frame( | |
| 167 _uriOrPathToUri(urlMatch[1]), | |
| 168 int.parse(urlMatch[2]), | |
| 169 int.parse(urlMatch[3]), | |
| 170 member); | |
| 171 } | |
| 172 | |
| 142 // V8 stack frames can be in two forms. | 173 // V8 stack frames can be in two forms. |
| 143 if (match[2] != null) { | 174 if (match[2] != null) { |
| 144 // The first form looks like " at FUNCTION (PATH:LINE:COL)". PATH is | 175 // The first form looks like " at FUNCTION (LOCATION)". |
| 145 // usually an absolute URL, but it can be a path if the stack frame came | 176 return parseLocation( |
| 146 // from d8. | 177 match[2], match[1].replaceAll("<anonymous>", "<fn>")); |
| 147 var uri = _uriOrPathToUri(match[2]); | |
| 148 var member = match[1].replaceAll("<anonymous>", "<fn>"); | |
| 149 return new Frame(uri, int.parse(match[3]), int.parse(match[4]), member); | |
| 150 } else { | 178 } else { |
| 151 // The second form looks like " at PATH:LINE:COL", and is used for | 179 // The second form looks like " at LOCATION", and is used for anonymous |
| 152 // anonymous functions. PATH is usually an absolute URL, but it can be a | 180 // functions. |
| 153 // path if the stack frame came from d8. | 181 return parseLocation(match[3], "<fn>"); |
| 154 var uri = _uriOrPathToUri(match[5]); | |
| 155 return new Frame(uri, int.parse(match[6]), int.parse(match[7]), "<fn>"); | |
| 156 } | 182 } |
| 157 } | 183 } |
| 158 | 184 |
| 159 /// Parses a string representation of an IE stack frame. | 185 /// Parses a string representation of an IE stack frame. |
| 160 /// | 186 /// |
| 161 /// IE10+ frames look just like V8 frames. Prior to IE10, stack traces can't | 187 /// IE10+ frames look just like V8 frames. Prior to IE10, stack traces can't |
| 162 /// be retrieved. | 188 /// be retrieved. |
| 163 factory Frame.parseIE(String frame) => new Frame.parseV8(frame); | 189 factory Frame.parseIE(String frame) => new Frame.parseV8(frame); |
| 164 | 190 |
| 165 /// Parses a string representation of a Firefox stack frame. | 191 /// Parses a string representation of a Firefox stack frame. |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 245 // their stack frames. However, if we do get a relative path, we should | 271 // their stack frames. However, if we do get a relative path, we should |
| 246 // handle it gracefully. | 272 // handle it gracefully. |
| 247 if (uriOrPath.contains('\\')) return path.windows.toUri(uriOrPath); | 273 if (uriOrPath.contains('\\')) return path.windows.toUri(uriOrPath); |
| 248 return Uri.parse(uriOrPath); | 274 return Uri.parse(uriOrPath); |
| 249 } | 275 } |
| 250 | 276 |
| 251 Frame(this.uri, this.line, this.column, this.member); | 277 Frame(this.uri, this.line, this.column, this.member); |
| 252 | 278 |
| 253 String toString() => '$location in $member'; | 279 String toString() => '$location in $member'; |
| 254 } | 280 } |
| OLD | NEW |