Better support for async VM frames.
Closes #1
R=kevmoo@google.com
Review URL: https://codereview.chromium.org//912043002
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2850cfc..25abd8a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,11 @@
+## 1.1.2
+
+* Support VM frames without line *or* column numbers, which async/await programs
+ occasionally generate.
+
+* Replace `<<anonymous closure>_async_body>` in VM frames' members with the
+ terser `<async>`.
+
## 1.1.1
* Widen the SDK constraint to include 1.7.0-dev.4.0.
diff --git a/lib/src/frame.dart b/lib/src/frame.dart
index 4f5b16c..8ecd19f 100644
--- a/lib/src/frame.dart
+++ b/lib/src/frame.dart
@@ -10,8 +10,9 @@
import 'trace.dart';
// #1 Foo._bar (file:///home/nweiz/code/stuff.dart:42:21)
-final _vmFrame = new RegExp(
- r'^#\d+\s+(\S.*) \((.+?):(\d+)(?::(\d+))?\)$');
+// #1 Foo._bar (file:///home/nweiz/code/stuff.dart:42)
+// #1 Foo._bar (file:///home/nweiz/code/stuff.dart)
+final _vmFrame = new RegExp(r'^#\d+\s+(\S.*) \((.+?)((?::\d+){0,2})\)$');
// at VW.call$0 (http://pub.dartlang.org/stuff.dart.js:560:28)
// at VW.call$0 (eval as fn
@@ -135,14 +136,14 @@
// Get the pieces out of the regexp match. Function, URI and line should
// always be found. The column is optional.
- var member = match[1].replaceAll("<anonymous closure>", "<fn>");
+ var member = match[1]
+ .replaceAll("<<anonymous closure>_async_body>", "<async>")
+ .replaceAll("<anonymous closure>", "<fn>");
var uri = Uri.parse(match[2]);
- var line = int.parse(match[3]);
- var column = null;
- var columnMatch = match[4];
- if (columnMatch != null) {
- column = int.parse(columnMatch);
- }
+
+ var lineAndColumn = match[3].split(':');
+ var line = lineAndColumn.length > 1 ? int.parse(lineAndColumn[1]) : null;
+ var column = lineAndColumn.length > 2 ? int.parse(lineAndColumn[2]) : null;
return new Frame(uri, line, column, member);
}
diff --git a/lib/src/vm_trace.dart b/lib/src/vm_trace.dart
index 8116015..89474f5 100644
--- a/lib/src/vm_trace.dart
+++ b/lib/src/vm_trace.dart
@@ -22,7 +22,9 @@
var i = 1;
return frames.map((frame) {
var number = padRight("#${i++}", 8);
- var member = frame.member.replaceAll("<fn>", "<anonymous closure>");
+ var member = frame.member
+ .replaceAll("<fn>", "<anonymous closure>")
+ .replaceAll("<async>", "<<anonymous closure>_async_body>");
var line = frame.line == null ? 0 : frame.line;
var column = frame.column == null ? 0 : frame.column;
return "$number$member (${frame.uri}:$line:$column)\n";
diff --git a/pubspec.yaml b/pubspec.yaml
index 8adfb2f..2fee061 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -7,7 +7,7 @@
#
# When the major version is upgraded, you *must* update that version constraint
# in pub to stay in sync with this.
-version: 1.1.1
+version: 1.1.2
author: "Dart Team <misc@dartlang.org>"
homepage: http://github.com/dart-lang/stack_trace
description: >
diff --git a/test/frame_test.dart b/test/frame_test.dart
index b132368..638d1d7 100644
--- a/test/frame_test.dart
+++ b/test/frame_test.dart
@@ -30,6 +30,17 @@
expect(frame.member, equals('Foo._bar'));
});
+ // This can happen with async stack traces. See issue 22009.
+ test('parses a stack frame without line or column correctly', () {
+ var frame = new Frame.parseVM("#1 Foo._bar "
+ "(file:///home/nweiz/code/stuff.dart)");
+ expect(frame.uri,
+ equals(Uri.parse("file:///home/nweiz/code/stuff.dart")));
+ expect(frame.line, isNull);
+ expect(frame.column, isNull);
+ expect(frame.member, equals('Foo._bar'));
+ });
+
test('converts "<anonymous closure>" to "<fn>"', () {
String parsedMember(String member) =>
new Frame.parseVM('#0 $member (foo:0:0)').member;
@@ -39,6 +50,18 @@
equals('<fn>.<fn>.bar'));
});
+ test('converts "<<anonymous closure>_async_body>" to "<async>"', () {
+ var frame = new Frame.parseVM(
+ '#0 Foo.<<anonymous closure>_async_body> (foo:0:0)');
+ expect(frame.member, equals('Foo.<async>'));
+ });
+
+ test('converts "<<anonymous closure>_async_body>" to "<async>"', () {
+ var frame = new Frame.parseVM(
+ '#0 Foo.<<anonymous closure>_async_body> (foo:0:0)');
+ expect(frame.member, equals('Foo.<async>'));
+ });
+
test('parses a folded frame correctly', () {
var frame = new Frame.parseVM('...');
@@ -52,8 +75,6 @@
expect(() => new Frame.parseVM(''), throwsFormatException);
expect(() => new Frame.parseVM('#1'), throwsFormatException);
expect(() => new Frame.parseVM('#1 Foo'), throwsFormatException);
- expect(() => new Frame.parseVM('#1 Foo (dart:async/future.dart)'),
- throwsFormatException);
expect(() => new Frame.parseVM('#1 (dart:async/future.dart:10:15)'),
throwsFormatException);
expect(() => new Frame.parseVM('Foo (dart:async/future.dart:10:15)'),