import { Subscription } from '../Subscription'; interface AnimationFrameProvider { schedule(callback: FrameRequestCallback): Subscription; requestAnimationFrame: typeof requestAnimationFrame; cancelAnimationFrame: typeof cancelAnimationFrame; delegate: | { requestAnimationFrame: typeof requestAnimationFrame; cancelAnimationFrame: typeof cancelAnimationFrame; } | undefined; } export const animationFrameProvider: AnimationFrameProvider = { // When accessing the delegate, use the variable rather than `this` so that // the functions can be called without being bound to the provider. schedule(callback) { let request = requestAnimationFrame; let cancel: typeof cancelAnimationFrame | undefined = cancelAnimationFrame; const { delegate } = animationFrameProvider; if (delegate) { request = delegate.requestAnimationFrame; cancel = delegate.cancelAnimationFrame; } const handle = request((timestamp) => { // Clear the cancel function. The request has been fulfilled, so // attempting to cancel the request upon unsubscription would be // pointless. cancel = undefined; callback(timestamp); }); return new Subscription(() => cancel?.(handle)); }, requestAnimationFrame(...args) { const { delegate } = animationFrameProvider; return (delegate?.requestAnimationFrame || requestAnimationFrame)(...args); }, cancelAnimationFrame(...args) { const { delegate } = animationFrameProvider; return (delegate?.cancelAnimationFrame || cancelAnimationFrame)(...args); }, delegate: undefined, };