@@ -746,8 +746,9 @@ function assertGreaterThanZero(dir: NgOptimizedImage, inputValue: unknown, input
746746 */
747747function assertNoImageDistortion (
748748 dir : NgOptimizedImage , img : HTMLImageElement , renderer : Renderer2 ) {
749- const removeListenerFn = renderer . listen ( img , 'load' , ( ) => {
750- removeListenerFn ( ) ;
749+ const removeLoadListenerFn = renderer . listen ( img , 'load' , ( ) => {
750+ removeLoadListenerFn ( ) ;
751+ removeErrorListenerFn ( ) ;
751752 const computedStyle = window . getComputedStyle ( img ) ;
752753 let renderedWidth = parseFloat ( computedStyle . getPropertyValue ( 'width' ) ) ;
753754 let renderedHeight = parseFloat ( computedStyle . getPropertyValue ( 'height' ) ) ;
@@ -828,6 +829,15 @@ function assertNoImageDistortion(
828829 }
829830 }
830831 } ) ;
832+
833+ // We only listen to the `error` event to remove the `load` event listener because it will not be
834+ // fired if the image fails to load. This is done to prevent memory leaks in development mode
835+ // because image elements aren't garbage-collected properly. It happens because zone.js stores the
836+ // event listener directly on the element and closures capture `dir`.
837+ const removeErrorListenerFn = renderer . listen ( img , 'error' , ( ) => {
838+ removeLoadListenerFn ( ) ;
839+ removeErrorListenerFn ( ) ;
840+ } ) ;
831841}
832842
833843/**
@@ -870,8 +880,9 @@ function assertEmptyWidthAndHeight(dir: NgOptimizedImage) {
870880 */
871881function assertNonZeroRenderedHeight (
872882 dir : NgOptimizedImage , img : HTMLImageElement , renderer : Renderer2 ) {
873- const removeListenerFn = renderer . listen ( img , 'load' , ( ) => {
874- removeListenerFn ( ) ;
883+ const removeLoadListenerFn = renderer . listen ( img , 'load' , ( ) => {
884+ removeLoadListenerFn ( ) ;
885+ removeErrorListenerFn ( ) ;
875886 const renderedHeight = img . clientHeight ;
876887 if ( dir . fill && renderedHeight === 0 ) {
877888 console . warn ( formatRuntimeError (
@@ -883,6 +894,12 @@ function assertNonZeroRenderedHeight(
883894 `property defined and the height of the element is not zero.` ) ) ;
884895 }
885896 } ) ;
897+
898+ // See comments in the `assertNoImageDistortion`.
899+ const removeErrorListenerFn = renderer . listen ( img , 'error' , ( ) => {
900+ removeLoadListenerFn ( ) ;
901+ removeErrorListenerFn ( ) ;
902+ } ) ;
886903}
887904
888905/**
0 commit comments