Skip to content
This repository was archived by the owner on Feb 10, 2025. It is now read-only.

Commit 45319bf

Browse files
author
Clement Skau
authored
Fix async gap handling. (#84)
Fix an issue where an async gap at the end of a stack trace would not get parsed correctly due to the trailing newline being `trim()`'d. Add tests to cover this case.
1 parent 7e63e5f commit 45319bf

File tree

4 files changed

+50
-2
lines changed

4 files changed

+50
-2
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
## 1.10.0-nullsafety.3-dev
22

3+
* Fix bug parsing asynchronous suspension gap markers at the end of stack
4+
traces.
5+
36
## 1.10.0-nullsafety.2
47

58
* Forward fix for a change in SDK type promotion behavior.

lib/src/trace.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,11 @@ class Trace implements StackTrace {
146146
static List<Frame> _parseVM(String trace) {
147147
// Ignore [vmChainGap]. This matches the behavior of
148148
// `Chain.parse().toTrace()`.
149-
var lines = trace.trim().replaceAll(vmChainGap, '').split('\n');
149+
var lines = trace
150+
.trim()
151+
.replaceAll(vmChainGap, '')
152+
.split('\n')
153+
.where((line) => line.isNotEmpty);
150154
var frames = lines
151155
.take(lines.length - 1)
152156
.map((line) => Frame.parseVM(line))

lib/src/utils.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const chainGap = '===== asynchronous gap ===========================\n';
88

99
/// The line used in the string representation of VM stack chains to represent
1010
/// the gap between traces.
11-
const vmChainGap = '<asynchronous suspension>\n';
11+
final vmChainGap = RegExp(r'^<asynchronous suspension>\n?$', multiLine: true);
1212

1313
// TODO(nweiz): When cross-platform imports work, use them to set this.
1414
/// Whether we're running in a JS context.

test/trace_test.dart

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,25 @@ void main() {
249249
equals(Uri.parse('https://dart.dev/foo/quux.dart')));
250250
});
251251

252+
test('parses a package:stack_trace stack chain with end gap correctly', () {
253+
var trace =
254+
Trace.parse('https://dart.dev/foo/bar.dart 10:11 Foo.<fn>.bar\n'
255+
'https://dart.dev/foo/baz.dart Foo.<fn>.bar\n'
256+
'https://dart.dev/foo/bang.dart 10:11 Foo.<fn>.bar\n'
257+
'https://dart.dev/foo/quux.dart Foo.<fn>.bar'
258+
'===== asynchronous gap ===========================\n');
259+
260+
expect(trace.frames.length, 4);
261+
expect(trace.frames[0].uri,
262+
equals(Uri.parse('https://dart.dev/foo/bar.dart')));
263+
expect(trace.frames[1].uri,
264+
equals(Uri.parse('https://dart.dev/foo/baz.dart')));
265+
expect(trace.frames[2].uri,
266+
equals(Uri.parse('https://dart.dev/foo/bang.dart')));
267+
expect(trace.frames[3].uri,
268+
equals(Uri.parse('https://dart.dev/foo/quux.dart')));
269+
});
270+
252271
test('parses a real package:stack_trace stack trace correctly', () {
253272
var traceString = Trace.current().toString();
254273
expect(Trace.parse(traceString).toString(), equals(traceString));
@@ -259,6 +278,28 @@ void main() {
259278
expect(trace.frames, isEmpty);
260279
expect(trace.toString(), equals(''));
261280
});
281+
282+
test('parses trace with async gap correctly', () {
283+
var trace = Trace.parse('#0 bop (file:///pull.dart:42:23)\n'
284+
'<asynchronous suspension>\n'
285+
'#1 twist (dart:the/future.dart:0:2)\n'
286+
'#2 main (dart:my/file.dart:4:6)\n');
287+
288+
expect(trace.frames.length, 3);
289+
expect(trace.frames[0].uri, equals(Uri.parse('file:///pull.dart')));
290+
expect(trace.frames[1].uri, equals(Uri.parse('dart:the/future.dart')));
291+
expect(trace.frames[2].uri, equals(Uri.parse('dart:my/file.dart')));
292+
});
293+
294+
test('parses trace with async gap at end correctly', () {
295+
var trace = Trace.parse('#0 bop (file:///pull.dart:42:23)\n'
296+
'#1 twist (dart:the/future.dart:0:2)\n'
297+
'<asynchronous suspension>\n');
298+
299+
expect(trace.frames.length, 2);
300+
expect(trace.frames[0].uri, equals(Uri.parse('file:///pull.dart')));
301+
expect(trace.frames[1].uri, equals(Uri.parse('dart:the/future.dart')));
302+
});
262303
});
263304

264305
test('.toString() nicely formats the stack trace', () {

0 commit comments

Comments
 (0)