Add a Trace.original field (#29)

Closes #28
diff --git a/CHANGELOG.md b/CHANGELOG.md
index abb5b0a..cd78a9a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+## 1.8.0
+
+* Add a `Trace.original` field to provide access to the original `StackTrace`s
+  from which the `Trace` was created, and a matching constructor parameter to
+  `new Trace()`.
+
 ## 1.7.4
 
 * Always run `onError` callbacks for `Chain.capture()` in the parent zone.
diff --git a/lib/src/chain.dart b/lib/src/chain.dart
index e93b2b4..2d1349d 100644
--- a/lib/src/chain.dart
+++ b/lib/src/chain.dart
@@ -134,8 +134,9 @@
     return new LazyChain(() {
       // JS includes a frame for the call to StackTrace.current, but the VM
       // doesn't, so we skip an extra frame in a JS context.
-      var first =
-          new Trace(chain.traces.first.frames.skip(level + (inJS ? 2 : 1)));
+      var first = new Trace(
+          chain.traces.first.frames.skip(level + (inJS ? 2 : 1)),
+          original: chain.traces.first.original.toString());
       return new Chain([first]..addAll(chain.traces.skip(1)));
     });
   }
diff --git a/lib/src/lazy_trace.dart b/lib/src/lazy_trace.dart
index 97bb391..a31b75f 100644
--- a/lib/src/lazy_trace.dart
+++ b/lib/src/lazy_trace.dart
@@ -23,6 +23,7 @@
   }
 
   List<Frame> get frames => _trace.frames;
+  StackTrace get original => _trace.original;
   StackTrace get vmTrace => _trace.vmTrace;
   Trace get terse => new LazyTrace(() => _trace.terse);
   Trace foldFrames(bool predicate(Frame frame), {bool terse: false}) =>
diff --git a/lib/src/stack_zone_specification.dart b/lib/src/stack_zone_specification.dart
index 924f2ef..eb06beb 100644
--- a/lib/src/stack_zone_specification.dart
+++ b/lib/src/stack_zone_specification.dart
@@ -232,6 +232,6 @@
     var trace = new Trace.parse(text);
     // JS includes a frame for the call to StackTrace.current, but the VM
     // doesn't, so we skip an extra frame in a JS context.
-    return new Trace(trace.frames.skip(level + (inJS ? 2 : 1)));
+    return new Trace(trace.frames.skip(level + (inJS ? 2 : 1)), original: text);
   });
 }
diff --git a/lib/src/trace.dart b/lib/src/trace.dart
index 6296df5..972c33e 100644
--- a/lib/src/trace.dart
+++ b/lib/src/trace.dart
@@ -60,6 +60,9 @@
   /// The stack frames that comprise this stack trace.
   final List<Frame> frames;
 
+  /// The original stack trace from which this trace was parsed.
+  final StackTrace original;
+
   /// Returns a human-readable representation of [stackTrace]. If [terse] is
   /// set, this folds together multiple stack frames from the Dart core
   /// libraries, so that only the core library method directly called from user
@@ -85,7 +88,8 @@
     return new LazyTrace(() {
       // JS includes a frame for the call to StackTrace.current, but the VM
       // doesn't, so we skip an extra frame in a JS context.
-      return new Trace(trace.frames.skip(level + (inJS ? 2 : 1)));
+      return new Trace(trace.frames.skip(level + (inJS ? 2 : 1)),
+          original: trace.original.toString());
     });
   }
 
@@ -134,7 +138,7 @@
   }
 
   /// Parses a string representation of a Dart VM stack trace.
-  Trace.parseVM(String trace) : this(_parseVM(trace));
+  Trace.parseVM(String trace) : this(_parseVM(trace), original: trace);
 
   static List<Frame> _parseVM(String trace) {
     // Ignore [vmChainGap]. This matches the behavior of
@@ -155,21 +159,25 @@
 
   /// Parses a string representation of a Chrome/V8 stack trace.
   Trace.parseV8(String trace)
-      : this(trace
-            .split("\n")
-            .skip(1)
-            // It's possible that an Exception's description contains a line that
-            // looks like a V8 trace line, which will screw this up.
-            // Unfortunately, that's impossible to detect.
-            .skipWhile((line) => !line.startsWith(_v8TraceLine))
-            .map((line) => new Frame.parseV8(line)));
+      : this(
+            trace
+                .split("\n")
+                .skip(1)
+                // It's possible that an Exception's description contains a line that
+                // looks like a V8 trace line, which will screw this up.
+                // Unfortunately, that's impossible to detect.
+                .skipWhile((line) => !line.startsWith(_v8TraceLine))
+                .map((line) => new Frame.parseV8(line)),
+            original: trace);
 
   /// Parses a string representation of a JavaScriptCore stack trace.
   Trace.parseJSCore(String trace)
-      : this(trace
-            .split("\n")
-            .where((line) => line != "\tat ")
-            .map((line) => new Frame.parseV8(line)));
+      : this(
+            trace
+                .split("\n")
+                .where((line) => line != "\tat ")
+                .map((line) => new Frame.parseV8(line)),
+            original: trace);
 
   /// Parses a string representation of an Internet Explorer stack trace.
   ///
@@ -179,11 +187,13 @@
 
   /// Parses a string representation of a Firefox stack trace.
   Trace.parseFirefox(String trace)
-      : this(trace
-            .trim()
-            .split("\n")
-            .where((line) => line.isNotEmpty && line != '[native code]')
-            .map((line) => new Frame.parseFirefox(line)));
+      : this(
+            trace
+                .trim()
+                .split("\n")
+                .where((line) => line.isNotEmpty && line != '[native code]')
+                .map((line) => new Frame.parseFirefox(line)),
+            original: trace);
 
   /// Parses a string representation of a Safari stack trace.
   Trace.parseSafari(String trace) : this.parseFirefox(trace);
@@ -195,28 +205,34 @@
   /// Parses a string representation of a Safari 6.0 stack trace.
   @Deprecated("Use Trace.parseSafari instead.")
   Trace.parseSafari6_0(String trace)
-      : this(trace
-            .trim()
-            .split("\n")
-            .where((line) => line != '[native code]')
-            .map((line) => new Frame.parseFirefox(line)));
+      : this(
+            trace
+                .trim()
+                .split("\n")
+                .where((line) => line != '[native code]')
+                .map((line) => new Frame.parseFirefox(line)),
+            original: trace);
 
   /// Parses this package's string representation of a stack trace.
   ///
   /// This also parses string representations of [Chain]s. They parse to the
   /// same trace that [Chain.toTrace] would return.
   Trace.parseFriendly(String trace)
-      : this(trace.isEmpty
-            ? []
-            : trace
-                .trim()
-                .split("\n")
-                // Filter out asynchronous gaps from [Chain]s.
-                .where((line) => !line.startsWith('====='))
-                .map((line) => new Frame.parseFriendly(line)));
+      : this(
+            trace.isEmpty
+                ? []
+                : trace
+                    .trim()
+                    .split("\n")
+                    // Filter out asynchronous gaps from [Chain]s.
+                    .where((line) => !line.startsWith('====='))
+                    .map((line) => new Frame.parseFriendly(line)),
+            original: trace);
 
   /// Returns a new [Trace] comprised of [frames].
-  Trace(Iterable<Frame> frames) : frames = new List<Frame>.unmodifiable(frames);
+  Trace(Iterable<Frame> frames, {String original})
+      : frames = new List<Frame>.unmodifiable(frames),
+        original = new StackTrace.fromString(original);
 
   /// Returns a VM-style [StackTrace] object.
   ///
@@ -297,7 +313,7 @@
       }
     }
 
-    return new Trace(newFrames.reversed);
+    return new Trace(newFrames.reversed, original: this.original.toString());
   }
 
   /// Returns a human-readable string representation of [this].
diff --git a/pubspec.yaml b/pubspec.yaml
index 3c25051..a4552ac 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.7.4
+version: 1.8.0
 author: "Dart Team <misc@dartlang.org>"
 homepage: https://github.com/dart-lang/stack_trace
 description: A package for manipulating stack traces and printing them readably.