Don't crash on stack overflow traces.

Closes #5

R=rnystrom@google.com

Review URL: https://codereview.chromium.org//1169883004.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8615187..36e9aa8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@
 
 * Add support for empty chains and chains of empty traces to `Chain.parse()`.
 
+* Don't crash when parsing stack traces from Dart VM stack overflows.
+
 ## 1.3.2
 
 * Don't crash when running `Trace.terse` on empty stack traces.
diff --git a/lib/src/trace.dart b/lib/src/trace.dart
index 418c4ab..4415161 100644
--- a/lib/src/trace.dart
+++ b/lib/src/trace.dart
@@ -134,10 +134,21 @@
 
   /// Parses a string representation of a Dart VM stack trace.
   Trace.parseVM(String trace)
-      : this(trace.trim().split("\n").
-            // TODO(nweiz): remove this when issue 15920 is fixed.
-            where((line) => line.isNotEmpty).
-            map((line) => new Frame.parseVM(line)));
+      : this(_parseVM(trace));
+
+  static List<Frame> _parseVM(String trace) {
+    var lines = trace.trim().split("\n");
+    var frames = lines.take(lines.length - 1)
+        .map((line) => new Frame.parseVM(line))
+        .toList();
+
+    // TODO(nweiz): Remove this when issue 23614 is fixed.
+    if (!lines.last.endsWith(".da")) {
+      frames.add(new Frame.parseVM(lines.last));
+    }
+
+    return frames;
+  }
 
   /// Parses a string representation of a Chrome/V8 stack trace.
   Trace.parseV8(String trace)
diff --git a/pubspec.yaml b/pubspec.yaml
index 9b8413d..578ecc9 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.3.3-dev
+version: 1.3.3
 author: "Dart Team <misc@dartlang.org>"
 homepage: http://github.com/dart-lang/stack_trace
 description: >
diff --git a/test/vm_test.dart b/test/vm_test.dart
index 48ca375..947f14b 100644
--- a/test/vm_test.dart
+++ b/test/vm_test.dart
@@ -56,6 +56,19 @@
       expect(trace.frames.first.member, equals('getStackTraceObject'));
     });
 
+    test('.from handles a stack overflow trace correctly', () {
+      overflow() => overflow();
+
+      var trace;
+      try {
+        overflow();
+      } catch (_, stackTrace) {
+        trace = new Trace.from(stackTrace);
+      }
+
+      expect(trace.frames.first.member, equals('main.<fn>.<fn>.overflow'));
+    });
+
     group('.current()', () {
       test('with no argument returns a trace starting at the current frame',
           () {