@@ -607,45 +607,66 @@ export function inDom(n: Node): boolean {
607
607
return doc . contains ( n ) || shadowHostInDom ( n ) ;
608
608
}
609
609
610
- let cachedRequestAnimationFrameImplementation :
611
- | undefined
612
- | typeof requestAnimationFrame ;
613
-
614
610
/**
615
- * We generally want to use window.requestAnimationFrame.
611
+ * We generally want to use window.requestAnimationFrame / window.setTimeout / window.clearTimeout .
616
612
* However, in some cases this may be wrapped (e.g. by Zone.js for Angular),
617
613
* so we try to get an unpatched version of this from a sandboxed iframe.
618
614
*/
619
- function getRequestAnimationFrameImplementation ( ) : typeof requestAnimationFrame {
620
- if ( cachedRequestAnimationFrameImplementation ) {
621
- return cachedRequestAnimationFrameImplementation ;
615
+
616
+ interface CacheableImplementations {
617
+ requestAnimationFrame : typeof requestAnimationFrame ;
618
+ setTimeout : typeof setTimeout ;
619
+ clearTimeout : typeof clearTimeout ;
620
+ }
621
+
622
+ const cachedImplementations : Partial < CacheableImplementations > = { } ;
623
+
624
+ function getImplementation < T extends keyof CacheableImplementations > (
625
+ name : T ,
626
+ ) : CacheableImplementations [ T ] {
627
+ const cached = cachedImplementations [ name ] ;
628
+ if ( cached ) {
629
+ return cached ;
622
630
}
623
631
624
632
const document = window . document ;
625
- let requestAnimationFrameImplementation = window . requestAnimationFrame ;
633
+ let impl = window [ name ] as CacheableImplementations [ T ] ;
626
634
if ( document && typeof document . createElement === 'function' ) {
627
635
try {
628
636
const sandbox = document . createElement ( 'iframe' ) ;
629
637
sandbox . hidden = true ;
630
638
document . head . appendChild ( sandbox ) ;
631
639
const contentWindow = sandbox . contentWindow ;
632
- if ( contentWindow && contentWindow . requestAnimationFrame ) {
633
- requestAnimationFrameImplementation =
640
+ if ( contentWindow && contentWindow [ name ] ) {
641
+ impl =
634
642
// eslint-disable-next-line @typescript-eslint/unbound-method
635
- contentWindow . requestAnimationFrame ;
643
+ contentWindow [ name ] as CacheableImplementations [ T ] ;
636
644
}
637
645
document . head . removeChild ( sandbox ) ;
638
646
} catch ( e ) {
639
- // Could not create sandbox iframe, just use window.requestAnimationFrame
647
+ // Could not create sandbox iframe, just use window.xxx
640
648
}
641
649
}
642
650
643
- return ( cachedRequestAnimationFrameImplementation =
644
- requestAnimationFrameImplementation . bind ( window ) ) ;
651
+ return ( cachedImplementations [ name ] = impl . bind (
652
+ window ,
653
+ ) as CacheableImplementations [ T ] ) ;
645
654
}
646
655
647
656
export function onRequestAnimationFrame (
648
657
...rest : Parameters < typeof requestAnimationFrame >
649
658
) : ReturnType < typeof requestAnimationFrame > {
650
- return getRequestAnimationFrameImplementation ( ) ( ...rest ) ;
659
+ return getImplementation ( 'requestAnimationFrame' ) ( ...rest ) ;
660
+ }
661
+
662
+ export function setTimeout (
663
+ ...rest : Parameters < typeof window . setTimeout >
664
+ ) : ReturnType < typeof window . setTimeout > {
665
+ return getImplementation ( 'setTimeout' ) ( ...rest ) ;
666
+ }
667
+
668
+ export function clearTimeout (
669
+ ...rest : Parameters < typeof window . clearTimeout >
670
+ ) : ReturnType < typeof window . clearTimeout > {
671
+ return getImplementation ( 'clearTimeout' ) ( ...rest ) ;
651
672
}
0 commit comments