Fold empty async frames when generating a terse stack trace.

This avoids having stack chains with a bunch of useless empty frames.

R=rnystrom@google.com, kevmoo@google.com

Review URL: https://codereview.chromium.org//921553006
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 25abd8a..edd8ba6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 1.1.3
+
+* Produce nicer-looking stack chains when using the VM's async/await
+  implementation.
+
 ## 1.1.2
 
 * Support VM frames without line *or* column numbers, which async/await programs
diff --git a/lib/src/trace.dart b/lib/src/trace.dart
index 2690ece..5cd09e9 100644
--- a/lib/src/trace.dart
+++ b/lib/src/trace.dart
@@ -205,7 +205,18 @@
   /// removed.
   Trace get terse {
     return new Trace(foldFrames((frame) {
-      return frame.isCore || frame.package == 'stack_trace';
+      if (frame.isCore) return true;
+      if (frame.package == 'stack_trace') return true;
+
+      // Ignore async stack frames without any line or column information. These
+      // come from the VM's async/await implementation and represent internal
+      // frames. They only ever show up in stack chains and are always
+      // surrounded by other traces that are actually useful, so we can just get
+      // rid of them.
+      // TODO(nweiz): Get rid of this logic some time after issue 22009 is
+      // fixed.
+      if (!frame.member.contains('<async>')) return false;
+      return frame.line == null;
     }).frames.map((frame) {
       if (!frame.isCore) return frame;
       var library = frame.library.replaceAll(_terseRegExp, '');
diff --git a/pubspec.yaml b/pubspec.yaml
index 2fee061..ded96f6 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.2
+version: 1.1.3
 author: "Dart Team <misc@dartlang.org>"
 homepage: http://github.com/dart-lang/stack_trace
 description: >
diff --git a/test/trace_test.dart b/test/trace_test.dart
index 17f9c22..c8a848b 100644
--- a/test/trace_test.dart
+++ b/test/trace_test.dart
@@ -283,6 +283,20 @@
 '''));
   });
 
+  test('.terse folds empty async frames', () {
+    var trace = new Trace.parse('''
+#0 notCore (foo.dart:42:21)
+#1 top (dart:async/future.dart:0:2)
+#2 empty.<<anonymous closure>_async_body> (bar.dart)
+#3 bottom (dart:async-patch/future.dart:9:11)
+''');
+
+    expect(trace.terse.toString(), equals('''
+foo.dart 42:21  notCore
+dart:async      bottom
+'''));
+  });
+
   test('.foldFrames folds frames together bottom-up', () {
     var trace = new Trace.parse('''
 #0 notFoo (foo.dart:42:21)