import { DOMException } from "@miniflare/core" ; import { assertInRequest , waitForOpenInputGate } from "@miniflare/shared" ; export type TimerFunction < Return > = < Args extends any [ ] > ( callback : ( ... args : Args ) => void , ms ? : number , ... args : Args ) => Return ; export function createTimer < Return > ( func , blockGlobalTimers = false ) { return ( callback , ms , ... args ) => { if ( blockGlobalTimers ) assertInRequest ( ) ; return func ( callback ? async ( ... args ) => { await waitForOpenInputGate ( ) ; callback ?. ( ... args ) ; } : callback , ms , ... args ) ; } ; } export const AbortSignal = globalThis . AbortSignal ?? Object . getPrototypeOf ( new AbortController ( ) . signal ) . constructor ; AbortSignal . timeout = function ( ms ? ) { if ( arguments . length === 0 ) { throw new TypeError ( "Failed to execute 'timeout' on 'AbortSignal': parameter 1 is not of type 'integer'." ) ; } const controller = new AbortController ( ) ; setTimeout ( ( ) => controller . abort ( ) , ms ) ; return controller . signal ; } ; export interface SchedulerWaitOptions { signal ? : AbortSignal ; } export class Scheduler { readonly #blockGlobalTimers : boolean ; constructor ( blockGlobalTimers = false ) { this . #blockGlobalTimers = blockGlobalTimers ; } wait ( ms ? , options ? ) { if ( this . #blockGlobalTimers ) assertInRequest ( ) ; if ( arguments . length === 0 ) { throw new TypeError ( "Failed to execute 'wait' on 'Scheduler': parameter 1 is not of type 'integer'." ) ; } return new Promise ( ( resolve , reject ) => { let resolved = false ; const timeout = setTimeout ( ( ) => ( resolved = true ) && resolve ( ) , ms ) ; options ?. signal ?. addEventListener ( "abort" , ( ) => { if ( resolved ) return ; clearTimeout ( timeout ) ; reject ( new DOMException ( "The operation was aborted" , "AbortError" ) ) ; } ) ; } ) ; } }