Fix friendly frame parsing bugs. Fix bug parsing a friendly frame with spaces in the member name. Fix bug parsing a friendly frame where the location is a data url. BUG= R=nweiz@google.com Review-Url: https://codereview.chromium.org//2739643004 .
diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 293538f..53cdd37 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md
@@ -1,3 +1,7 @@ +## 1.7.2 +* Fix bug parsing a friendly frame with spaces in the member name. +* Fix bug parsing a friendly frame where the location is a data url. + ## 1.7.1 * Make `Trace.parse()`, `Chain.parse()`, treat the VM's new causal asynchronous
diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 8dde788..8599245 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart
@@ -52,9 +52,11 @@ r'$'); // foo/bar.dart 10:11 Foo._bar +// foo/bar.dart 10:11 (anonymous function).dart.fn // http://dartlang.org/foo/bar.dart Foo._bar +// data:... 10:11 Foo._bar final _friendlyFrame = new RegExp( - r'^(\S+)(?: (\d+)(?::(\d+))?)?\s+([^\d]\S*)$'); + r'^(\S+)(?: (\d+)(?::(\d+))?)?\s+([^\d].*)$'); /// A regular expression that matches asynchronous member names generated by the /// VM. @@ -186,7 +188,8 @@ // as "Anonymous function". return parseLocation(match[2], match[1].replaceAll("<anonymous>", "<fn>") - .replaceAll("Anonymous function", "<fn>")); + .replaceAll("Anonymous function", "<fn>") + .replaceAll("(anonymous function)", "<fn>")); } else { // The second form looks like " at LOCATION", and is used for anonymous // functions. @@ -249,8 +252,11 @@ throw new FormatException( "Couldn't parse package:stack_trace stack trace line '$frame'."); } - - var uri = Uri.parse(match[1]); + // Fake truncated data urls generated by the friendly stack trace format + // cause Uri.parse to throw an exception so we have to special case them. + var uri = match[1] == 'data:...' + ? new Uri.dataFromString('') + : Uri.parse(match[1]); // If there's no scheme, this is a relative URI. We should interpret it as // relative to the current working directory. if (uri.scheme == '') {
diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 4289a6e..dd081ea 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/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.1 +version: 1.7.2 author: "Dart Team <misc@dartlang.org>" homepage: https://github.com/dart-lang/stack_trace description: >
diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 080c8b8..a5f8b23 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart
@@ -448,7 +448,7 @@ expect(frame.member, equals('Foo.<fn>.bar')); }); - test('parses a stack frame with no line correctly', () { + test('parses a stack frame with no column correctly', () { var frame = new Frame.parseFriendly( "http://dartlang.org/foo/bar.dart 10 Foo.<fn>.bar"); expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); @@ -472,6 +472,45 @@ expectIsUnparsed((text) => new Frame.parseFriendly(text), 'foo/bar.dart 10:11'); }); + + test('parses a data url stack frame with no line or column correctly', () { + var frame = new Frame.parseFriendly( + "data:... main"); + expect(frame.uri.scheme, equals('data')); + expect(frame.line, isNull); + expect(frame.column, isNull); + expect(frame.member, equals('main')); + }); + + test('parses a data url stack frame correctly', () { + var frame = new Frame.parseFriendly( + "data:... 10:11 main"); + expect(frame.uri.scheme, equals('data')); + expect(frame.line, equals(10)); + expect(frame.column, equals(11)); + expect(frame.member, equals('main')); + }); + + test('parses a stack frame with spaces in the member name correctly', () { + var frame = new Frame.parseFriendly( + "foo/bar.dart 10:11 (anonymous function).dart.fn"); + expect(frame.uri, + equals(path.toUri(path.absolute(path.join('foo', 'bar.dart'))))); + expect(frame.line, equals(10)); + expect(frame.column, equals(11)); + expect(frame.member, equals('(anonymous function).dart.fn')); + }); + + test('parses a stack frame with spaces in the member name and no line or ' + 'column correctly', () { + var frame = new Frame.parseFriendly( + "http://dartlang.org/foo/bar.dart (anonymous function).dart.fn"); + expect( + frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); + expect(frame.line, isNull); + expect(frame.column, isNull); + expect(frame.member, equals('(anonymous function).dart.fn')); + }); }); test('only considers dart URIs to be core', () {
diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index 077f1ba..327eff0 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart
@@ -72,6 +72,23 @@ equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); expect(trace.frames[2].uri, equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + + trace = new Trace.parse( + 'Exception: foo\n' + ' bar\n' + ' at Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' + ' at http://pub.dartlang.org/stuff.js:0:2\n' + ' at (anonymous function).zip.zap ' + '(http://pub.dartlang.org/thing.js:1:100)'); + + expect(trace.frames[0].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[1].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[1].member, equals("<fn>")); + expect(trace.frames[2].uri, + equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + expect(trace.frames[2].member, equals("<fn>.zip.zap")); }); // JavaScriptCore traces are just like V8, except that it doesn't have a