Fix crash when a MultiFrameImageStreamCompleter is disposed during frame decoding (#69219)

This commit is contained in:
Dwayne Slater 2020-10-30 15:33:03 -07:00 committed by GitHub
parent 324b78eb12
commit 1fad8acb10
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 0 deletions

View File

@ -920,6 +920,12 @@ class MultiFrameImageStreamCompleter extends ImageStreamCompleter {
return;
}
if (_codec!.frameCount == 1) {
// ImageStreamCompleter listeners removed while waiting for next frame to
// be decoded.
// There's no reason to emit the frame without active listeners.
if (!hasListeners) {
return;
}
// This is not an animated image, just return it and don't schedule more
// frames.
_emitFrame(ImageInfo(

View File

@ -130,6 +130,31 @@ void main() {
expect(mockCodec.numFramesAsked, 1);
});
testWidgets('Decoding does not crash when disposed', (WidgetTester tester) async {
final Completer<Codec> completer = Completer<Codec>();
final MockCodec mockCodec = MockCodec();
mockCodec.frameCount = 1;
final ImageStreamCompleter imageStream = MultiFrameImageStreamCompleter(
codec: completer.future,
scale: 1.0,
);
completer.complete(mockCodec);
await tester.idle();
expect(mockCodec.numFramesAsked, 0);
final ImageListener listener = (ImageInfo image, bool synchronousCall) { };
final ImageStreamListener streamListener = ImageStreamListener(listener);
imageStream.addListener(streamListener);
await tester.idle();
expect(mockCodec.numFramesAsked, 1);
final FrameInfo frame = FakeFrameInfo(const Duration(milliseconds: 200), image20x10);
mockCodec.completeNextFrame(frame);
imageStream.removeListener(streamListener);
await tester.idle();
});
testWidgets('Chunk events of base ImageStreamCompleter are delivered', (WidgetTester tester) async {
final List<ImageChunkEvent> chunkEvents = <ImageChunkEvent>[];
final StreamController<ImageChunkEvent> streamController = StreamController<ImageChunkEvent>();