@@ -65,32 +65,33 @@ class CkBrowserImageDecoder implements ui.Codec {
6565 );
6666 }
6767
68-  final  _ImageDecoder  webDecoder =  _ImageDecoder (_ImageDecoderOptions (
69-  type:  contentType,
70-  data:  data,
68+  try  {
69+  final  _ImageDecoder  webDecoder =  _ImageDecoder (_ImageDecoderOptions (
70+  type:  contentType,
71+  data:  data,
7172
72-  // Flutter always uses premultiplied alpha. 
73-  premultiplyAlpha:  'premultiply' ,
74-  desiredWidth:  targetWidth,
75-  desiredHeight:  targetHeight,
73+    // Flutter always uses premultiplied alpha. 
74+    premultiplyAlpha:  'premultiply' ,
75+    desiredWidth:  targetWidth,
76+    desiredHeight:  targetHeight,
7677
77-  // "default" gives the browser the liberty to convert to display-appropriate 
78-  // color space, typically SRGB, which is what we want. 
79-  colorSpaceConversion:  'default' ,
78+    // "default" gives the browser the liberty to convert to display-appropriate 
79+    // color space, typically SRGB, which is what we want. 
80+    colorSpaceConversion:  'default' ,
8081
81-  // Flutter doesn't give the developer a way to customize this, so if this 
82-  // is an animated image we should prefer the animated track. 
83-  preferAnimation:  true ,
84-  ));
82+    // Flutter doesn't give the developer a way to customize this, so if this 
83+    // is an animated image we should prefer the animated track. 
84+    preferAnimation:  true ,
85+    ));
8586
86-  try  {
8787 await  js_util.promiseToFuture <void >(webDecoder.tracks.ready);
8888
8989 // Flutter doesn't have an API for progressive loading of images, so we 
9090 // wait until the image is fully decoded. 
9191 // package:js bindings don't work with getters that return a Promise, which 
9292 // is why js_util is used instead. 
9393 await  js_util.promiseToFuture <void >(js_util.getProperty (webDecoder, 'completed' ));
94+  return  CkBrowserImageDecoder ._(webDecoder, debugSource);
9495 } catch  (error) {
9596 if  (error is  html.DomException ) {
9697 if  (error.name ==  html.DomException .NOT_SUPPORTED ) {
@@ -106,7 +107,6 @@ class CkBrowserImageDecoder implements ui.Codec {
106107 'Original browser error: $error ' 
107108 );
108109 }
109-  return  CkBrowserImageDecoder ._(webDecoder, debugSource);
110110 }
111111
112112 CkBrowserImageDecoder ._(this .webDecoder, this .debugSource);
@@ -164,6 +164,13 @@ class CkBrowserImageDecoder implements ui.Codec {
164164 frame.displayWidth,
165165 frame.displayHeight,
166166 );
167+  // Duration can be null if the image is not animated. However, Flutter 
168+  // requires a non-null value. 0 indicates that the frame is meant to be 
169+  // displayed indefinitely, which is fine for a static image. 
170+  final  Duration  duration =  Duration (microseconds:  frame.duration ??  0 );
171+ 
172+  // Do not use the `frame` variable after this line. 
173+  frame.close ();
167174
168175 if  (skImage ==  null ) {
169176 throw  ImageCodecException (
@@ -172,12 +179,6 @@ class CkBrowserImageDecoder implements ui.Codec {
172179 }
173180
174181 final  CkImage  image =  CkImage (skImage);
175- 
176-  // Duration can be null if the image is not animated. However, Flutter 
177-  // requires a non-null value. 0 indicates that the frame is meant to be 
178-  // displayed indefinitely, which is fine for a static image. 
179-  final  Duration  duration =  Duration (microseconds:  frame.duration ??  0 );
180- 
181182 return  Future <ui.FrameInfo >.value (AnimatedImageFrameInfo (duration, image));
182183 }
183184
@@ -254,6 +255,7 @@ class _VideoFrame {
254255 external  int  get  displayWidth;
255256 external  int  get  displayHeight;
256257 external  int ?  get  duration;
258+  external  void  close ();
257259}
258260
259261/// Corresponds to the browser's `ImageTrackList`  type. 
0 commit comments