import _Concurrency import _CJavaScriptEventLoop import _CJavaScriptKit @available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *) extension JavaScriptEventLoop { static func installByLegacyHook() { #if compiler(>=5.9) typealias swift_task_asyncMainDrainQueue_hook_Fn = @convention(thin) ( swift_task_asyncMainDrainQueue_original, swift_task_asyncMainDrainQueue_override ) -> Void let swift_task_asyncMainDrainQueue_hook_impl: swift_task_asyncMainDrainQueue_hook_Fn = { _, _ in swjs_unsafe_event_loop_yield() } swift_task_asyncMainDrainQueue_hook = unsafeBitCast( swift_task_asyncMainDrainQueue_hook_impl, to: UnsafeMutableRawPointer?.self ) #endif typealias swift_task_enqueueGlobal_hook_Fn = @convention(thin) (UnownedJob, swift_task_enqueueGlobal_original) -> Void let swift_task_enqueueGlobal_hook_impl: swift_task_enqueueGlobal_hook_Fn = { job, original in JavaScriptEventLoop.shared.unsafeEnqueue(job) } swift_task_enqueueGlobal_hook = unsafeBitCast( swift_task_enqueueGlobal_hook_impl, to: UnsafeMutableRawPointer?.self ) typealias swift_task_enqueueGlobalWithDelay_hook_Fn = @convention(thin) ( UInt64, UnownedJob, swift_task_enqueueGlobalWithDelay_original ) -> Void let swift_task_enqueueGlobalWithDelay_hook_impl: swift_task_enqueueGlobalWithDelay_hook_Fn = { nanoseconds, job, original in let milliseconds = Double(nanoseconds / 1_000_000) JavaScriptEventLoop.shared.enqueue(job, withDelay: milliseconds) } swift_task_enqueueGlobalWithDelay_hook = unsafeBitCast( swift_task_enqueueGlobalWithDelay_hook_impl, to: UnsafeMutableRawPointer?.self ) #if compiler(>=5.7) typealias swift_task_enqueueGlobalWithDeadline_hook_Fn = @convention(thin) ( Int64, Int64, Int64, Int64, Int32, UnownedJob, swift_task_enqueueGlobalWithDelay_original ) -> Void let swift_task_enqueueGlobalWithDeadline_hook_impl: swift_task_enqueueGlobalWithDeadline_hook_Fn = { sec, nsec, tsec, tnsec, clock, job, original in JavaScriptEventLoop.shared.enqueue(job, withDelay: sec, nsec, tsec, tnsec, clock) } swift_task_enqueueGlobalWithDeadline_hook = unsafeBitCast( swift_task_enqueueGlobalWithDeadline_hook_impl, to: UnsafeMutableRawPointer?.self ) #endif typealias swift_task_enqueueMainExecutor_hook_Fn = @convention(thin) ( UnownedJob, swift_task_enqueueMainExecutor_original ) -> Void let swift_task_enqueueMainExecutor_hook_impl: swift_task_enqueueMainExecutor_hook_Fn = { job, original in JavaScriptEventLoop.shared.unsafeEnqueue(job) } swift_task_enqueueMainExecutor_hook = unsafeBitCast( swift_task_enqueueMainExecutor_hook_impl, to: UnsafeMutableRawPointer?.self ) } } #if compiler(>=5.7) /// Taken from https://github.com/apple/swift/blob/d375c972f12128ec6055ed5f5337bfcae3ec67d8/stdlib/public/Concurrency/Clock.swift#L84-L88 @_silgen_name("swift_get_time") internal func swift_get_time( _ seconds: UnsafeMutablePointer, _ nanoseconds: UnsafeMutablePointer, _ clock: CInt ) @available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *) extension JavaScriptEventLoop { fileprivate func enqueue( _ job: UnownedJob, withDelay seconds: Int64, _ nanoseconds: Int64, _ toleranceSec: Int64, _ toleranceNSec: Int64, _ clock: Int32 ) { var nowSec: Int64 = 0 var nowNSec: Int64 = 0 swift_get_time(&nowSec, &nowNSec, clock) let delayMilliseconds = (seconds - nowSec) * 1_000 + (nanoseconds - nowNSec) / 1_000_000 enqueue(job, withDelay: delayMilliseconds <= 0 ? 0 : Double(delayMilliseconds)) } } #endif