Skip to content

Commit 2458e1a

Browse files
authored
[fix,async] exception in async _CancelOnErrorSubscriptionWrapper.onError (#855)
1 parent 3b35aca commit 2458e1a

File tree

6 files changed

+108
-6
lines changed

6 files changed

+108
-6
lines changed

pkgs/async/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 2.13.0
2+
3+
- Fix type check and cast in SubscriptionStream's cancelOnError wrapper
4+
15
## 2.12.0
26

37
- Require Dart 3.4.

pkgs/async/lib/src/result/error.dart

+7-2
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,15 @@ class ErrorResult implements Result<Never> {
4747
/// has to be a function expecting only one argument, which will be called
4848
/// with only the error.
4949
void handle(Function errorHandler) {
50-
if (errorHandler is ZoneBinaryCallback) {
50+
if (errorHandler is dynamic Function(Object, StackTrace)) {
5151
errorHandler(error, stackTrace);
52+
} else if (errorHandler is dynamic Function(Object)) {
53+
errorHandler(error);
5254
} else {
53-
(errorHandler as ZoneUnaryCallback)(error);
55+
throw ArgumentError(
56+
'is neither Function(Object, StackTrace) nor Function(Object)',
57+
'errorHandler',
58+
);
5459
}
5560
}
5661

pkgs/async/lib/src/subscription_stream.dart

+3-3
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,10 @@ class _CancelOnErrorSubscriptionWrapper<T>
7676
super.onError((Object error, StackTrace stackTrace) {
7777
// Wait for the cancel to complete before sending the error event.
7878
super.cancel().whenComplete(() {
79-
if (handleError is ZoneBinaryCallback) {
79+
if (handleError is dynamic Function(Object, StackTrace)) {
8080
handleError(error, stackTrace);
81-
} else if (handleError != null) {
82-
(handleError as ZoneUnaryCallback)(error);
81+
} else if (handleError is dynamic Function(Object)) {
82+
handleError(error);
8383
}
8484
});
8585
});

pkgs/async/pubspec.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: async
2-
version: 2.12.0
2+
version: 2.13.0
33
description: Utility functions and classes related to the 'dart:async' library.
44
repository: https://github.com/dart-lang/core/tree/main/pkgs/async
55
issue_tracker: https://github.com/dart-lang/core/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Aasync

pkgs/async/test/result/result_test.dart

+23
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,29 @@ void main() {
281281
expect(called, isTrue);
282282
});
283283

284+
test('handle typed binary', () {
285+
final result = ErrorResult('error', stack);
286+
var called = false;
287+
void f(Object error, StackTrace stackTrace) {
288+
called = true;
289+
}
290+
291+
result.handle(f);
292+
expect(called, isTrue);
293+
});
294+
295+
test('handle typed unary', () {
296+
final result = ErrorResult('error', stack);
297+
var called = false;
298+
299+
void f(Object error) {
300+
called = true;
301+
}
302+
303+
result.handle(f);
304+
expect(called, isTrue);
305+
});
306+
284307
test('handle unary and binary', () {
285308
var result = ErrorResult('error', stack);
286309
var called = false;

pkgs/async/test/subscription_stream_test.dart

+70
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,76 @@ void main() {
148148
});
149149
}
150150
});
151+
152+
group('subscriptionStream error callback', () {
153+
test('binary typed', () async {
154+
var completer = Completer<void>();
155+
var stream = createErrorStream();
156+
var sourceSubscription = stream.listen(null, cancelOnError: true);
157+
var subscriptionStream = SubscriptionStream(sourceSubscription);
158+
159+
void f(Object error, StackTrace stackTrace) {
160+
completer.complete();
161+
}
162+
163+
subscriptionStream.listen((_) {},
164+
onError: f,
165+
onDone: () => throw 'should not happen',
166+
cancelOnError: true);
167+
await completer.future;
168+
await flushMicrotasks();
169+
});
170+
171+
test('binary dynamic', () async {
172+
var completer = Completer<void>();
173+
var stream = createErrorStream();
174+
var sourceSubscription = stream.listen(null, cancelOnError: true);
175+
var subscriptionStream = SubscriptionStream(sourceSubscription);
176+
177+
subscriptionStream.listen((_) {},
178+
onError: (error, stackTrace) {
179+
completer.complete();
180+
},
181+
onDone: () => throw 'should not happen',
182+
cancelOnError: true);
183+
await completer.future;
184+
await flushMicrotasks();
185+
});
186+
187+
test('unary typed', () async {
188+
var completer = Completer<void>();
189+
var stream = createErrorStream();
190+
var sourceSubscription = stream.listen(null, cancelOnError: true);
191+
var subscriptionStream = SubscriptionStream(sourceSubscription);
192+
193+
void f(Object error) {
194+
completer.complete();
195+
}
196+
197+
subscriptionStream.listen((_) {},
198+
onError: f,
199+
onDone: () => throw 'should not happen',
200+
cancelOnError: true);
201+
await completer.future;
202+
await flushMicrotasks();
203+
});
204+
205+
test('unary dynamic', () async {
206+
var completer = Completer<void>();
207+
var stream = createErrorStream();
208+
var sourceSubscription = stream.listen(null, cancelOnError: true);
209+
var subscriptionStream = SubscriptionStream(sourceSubscription);
210+
211+
subscriptionStream.listen((_) {},
212+
onError: (error) {
213+
completer.complete();
214+
},
215+
onDone: () => throw 'should not happen',
216+
cancelOnError: true);
217+
await completer.future;
218+
await flushMicrotasks();
219+
});
220+
});
151221
}
152222

153223
Stream<int> createStream() async* {

0 commit comments

Comments
 (0)