param timestamp export type FrameCallback = ( timestamp : DOMHighResTimeStamp ) => void ; param handle export type CancelFrame = ( handle : unknown ) => void ; returns export type GetTimestamp = ( ) => DOMHighResTimeStamp ; param callback returns export type RequestFrame = ( callback : FrameCallback ) => unknown ; /**
 * Hooks for retrieving and scheduling timing.
 */ export interface FrameTiming { /**
     * Cancels a next tick (by default, `cancelAnimationFrame`).
     */ cancelFrame : CancelFrame ; /**
     * Gets a current timestamp (by default, `performance.now`).
     */ getTimestamp : GetTimestamp ; /**
     * Schedules a next tick (by default, `requestAnimationFrame`).
     */ requestFrame : RequestFrame ; } param getTimestamp returns export const createFrameTiming = ( getTimestamp = ( ) => performance . now ( ) ) : FrameTiming => { const messagePrefix = `FrameTickrMessageData${ Math . random ( ) }` ; const callbacks = { } ; let callHandles = 0 ; const cancelFrame = ( handle ) => { delete callbacks [ handle ] ; } ; const onMessage = ( event ) => { if ( event . source !== window || typeof event . data !== "string" || event . data . indexOf ( messagePrefix ) === - 1 ) { return ; } const callback = callbacks [ event . data . substring ( messagePrefix . length ) ] ; if ( ! callback ) { return ; } callback ( getTimestamp ( ) ) ; } ; const requestFrame = ( callback ) => { const newHandle = `${ ( callHandles += 1 ) }` ; callbacks [ newHandle ] = callback ; window . postMessage ( `${ messagePrefix }${ newHandle }` , "*" ) ; return newHandle ; } ; window . addEventListener ( "message" , onMessage ) ; return { cancelFrame , getTimestamp , requestFrame } ; } ;