@@ -39,6 +39,7 @@ export default class Synchronizer {
3939 constructor ( primary , secondary ) {
4040 this . primary = primary ;
4141 this . secondary = secondary ;
42+ this . listeners = [ ] ;
4243
4344 this . status = {
4445 primary : 'waiting' ,
@@ -50,66 +51,91 @@ export default class Synchronizer {
5051 this . init ( ) ;
5152 }
5253
54+ _on ( target , event , callback ) {
55+ target . on ( event , callback ) ;
56+ this . listeners . push ( { target, event, callback } ) ;
57+ }
58+
59+ destroy ( ) {
60+ this . listeners . forEach ( ( { target, event, callback } ) => {
61+ target . off ( event , callback ) ;
62+ } ) ;
63+ this . listeners = [ ] ;
64+
65+ if ( this . visibilityHandler ) {
66+ document . removeEventListener ( 'visibilitychange' , this . visibilityHandler ) ;
67+ this . visibilityHandler = null ;
68+ }
69+ }
70+
5371 init ( ) {
5472 STATUSES . forEach ( status => {
55- this . primary . on ( status , ( ) => this . status . primary = status ) ;
56- this . secondary . on ( status , ( ) => this . status . secondary = status ) ;
73+ this . _on ( this . primary , status , ( ) => this . status . primary = status ) ;
74+ this . _on ( this . secondary , status , ( ) => this . status . secondary = status ) ;
5775 } ) ;
5876
59- this . primary . on ( 'play' , ( ) => this . secondary . play ( ) ) ;
60- this . primary . on ( 'pause' , ( ) => this . secondary . pause ( ) ) ;
77+ this . _on ( this . primary , 'play' , ( ) => {
78+ if ( ! this . secondary ?. isDisposed ?. ( ) ) this . secondary ?. play ( ) ;
79+ } ) ;
80+ this . _on ( this . primary , 'pause' , ( ) => {
81+ if ( ! this . secondary ?. isDisposed ?. ( ) ) this . secondary ?. pause ( ) ;
82+ } ) ;
6183
62- this . primary . on ( 'seeking' , ( ) => {
84+ this . _on ( this . primary , 'seeking' , ( ) => {
85+ if ( this . primary . isDisposed ?. ( ) ) return ;
6386 const currentTime = this . primary . currentTime ( ) ;
64- this . secondary . currentTime ( currentTime ) ;
87+ if ( ! this . secondary ?. isDisposed ?. ( ) ) this . secondary ? .currentTime ( currentTime ) ;
6588 } ) ;
6689
67- this . primary . on ( 'ratechange' , ( ) => {
90+ this . _on ( this . primary , 'ratechange' , ( ) => {
91+ if ( this . primary . isDisposed ?. ( ) ) return ;
6892 const playbackRate = this . primary . playbackRate ( ) ;
69- this . secondary . playbackRate ( playbackRate ) ;
93+ if ( ! this . secondary ?. isDisposed ?. ( ) ) this . secondary ? .playbackRate ( playbackRate ) ;
7094 } ) ;
7195
72- this . primary . on ( 'waiting' , ( ) => {
96+ this . _on ( this . primary , 'waiting' , ( ) => {
7397 if ( ! this . synching && this . status . secondary === 'canplay' ) {
7498 this . synching = true ;
75- this . primary . pause ( ) ;
99+ if ( ! this . primary . isDisposed ?. ( ) ) this . primary . pause ( ) ;
76100 }
77101 } ) ;
78102
79- this . primary . on ( 'canplay' , ( ) => {
103+ this . _on ( this . primary , 'canplay' , ( ) => {
80104 if ( this . synching ) {
81105 this . synching = false ;
82- this . primary . play ( ) ;
106+ if ( ! this . primary . isDisposed ?. ( ) ) this . primary . play ( ) ;
83107 }
84108 } ) ;
85109
86- this . secondary . on ( 'waiting' , ( ) => {
110+ this . _on ( this . secondary , 'waiting' , ( ) => {
87111 if ( ! this . synching && this . status . primary === 'canplay' ) {
88112 this . synching = true ;
89- this . primary . pause ( ) ;
113+ if ( ! this . primary . isDisposed ?. ( ) ) this . primary . pause ( ) ;
90114 }
91115 } ) ;
92116
93- this . secondary . on ( 'canplay' , ( ) => {
117+ this . _on ( this . secondary , 'canplay' , ( ) => {
94118 if ( this . synching ) {
95119 this . synching = false ;
96- this . primary . play ( ) ;
120+ if ( ! this . primary . isDisposed ?. ( ) ) this . primary . play ( ) ;
97121 }
98122 } ) ;
99123
100124 // IMPORTANT: Blink holds the secondary media down while the document
101125 // page is not visible
102126 // Force medias to sync on visibility change and document is visible
103- document . addEventListener ( 'visibilitychange' , ( ) => {
127+ this . visibilityHandler = ( ) => {
104128 if ( document . visibilityState === 'visible' ) {
129+ if ( this . primary . isDisposed ?. ( ) ) return ;
105130 const currentTime = this . primary . currentTime ( ) ;
106- this . secondary . currentTime ( currentTime ) ;
131+ if ( ! this . secondary ?. isDisposed ?. ( ) ) this . secondary ? .currentTime ( currentTime ) ;
107132 }
108- } ) ;
133+ } ;
134+ document . addEventListener ( 'visibilitychange' , this . visibilityHandler ) ;
109135
110136 EVENTS . forEach ( event => {
111- this . primary . on ( event , ( ) => logger . debug ( `primary ${ event } ${ this . status . primary } ` ) ) ;
112- this . secondary . on ( event , ( ) => logger . debug ( `secondary ${ event } ${ this . status . secondary } ` ) ) ;
137+ this . _on ( this . primary , event , ( ) => logger . debug ( `primary ${ event } ${ this . status . primary } ` ) ) ;
138+ this . _on ( this . secondary , event , ( ) => logger . debug ( `secondary ${ event } ${ this . status . secondary } ` ) ) ;
113139 } ) ;
114140 }
115141}
0 commit comments