Skip to content

Commit 0896c7d

Browse files
Split out the letacy hook-based global task executor
1 parent dd20832 commit 0896c7d

File tree

2 files changed

+110
-99
lines changed

2 files changed

+110
-99
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import _CJavaScriptEventLoop
2+
import _CJavaScriptKit
3+
4+
@available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)
5+
extension JavaScriptEventLoop {
6+
7+
static func installByLegacyHook() {
8+
#if compiler(>=5.9)
9+
typealias swift_task_asyncMainDrainQueue_hook_Fn = @convention(thin) (
10+
swift_task_asyncMainDrainQueue_original, swift_task_asyncMainDrainQueue_override
11+
) -> Void
12+
let swift_task_asyncMainDrainQueue_hook_impl: swift_task_asyncMainDrainQueue_hook_Fn = { _, _ in
13+
swjs_unsafe_event_loop_yield()
14+
}
15+
swift_task_asyncMainDrainQueue_hook = unsafeBitCast(
16+
swift_task_asyncMainDrainQueue_hook_impl,
17+
to: UnsafeMutableRawPointer?.self
18+
)
19+
#endif
20+
21+
typealias swift_task_enqueueGlobal_hook_Fn = @convention(thin) (UnownedJob, swift_task_enqueueGlobal_original)
22+
-> Void
23+
let swift_task_enqueueGlobal_hook_impl: swift_task_enqueueGlobal_hook_Fn = { job, original in
24+
JavaScriptEventLoop.shared.unsafeEnqueue(job)
25+
}
26+
swift_task_enqueueGlobal_hook = unsafeBitCast(
27+
swift_task_enqueueGlobal_hook_impl,
28+
to: UnsafeMutableRawPointer?.self
29+
)
30+
31+
typealias swift_task_enqueueGlobalWithDelay_hook_Fn = @convention(thin) (
32+
UInt64, UnownedJob, swift_task_enqueueGlobalWithDelay_original
33+
) -> Void
34+
let swift_task_enqueueGlobalWithDelay_hook_impl: swift_task_enqueueGlobalWithDelay_hook_Fn = {
35+
delay,
36+
job,
37+
original in
38+
JavaScriptEventLoop.shared.enqueue(job, withDelay: delay)
39+
}
40+
swift_task_enqueueGlobalWithDelay_hook = unsafeBitCast(
41+
swift_task_enqueueGlobalWithDelay_hook_impl,
42+
to: UnsafeMutableRawPointer?.self
43+
)
44+
45+
#if compiler(>=5.7)
46+
typealias swift_task_enqueueGlobalWithDeadline_hook_Fn = @convention(thin) (
47+
Int64, Int64, Int64, Int64, Int32, UnownedJob, swift_task_enqueueGlobalWithDelay_original
48+
) -> Void
49+
let swift_task_enqueueGlobalWithDeadline_hook_impl: swift_task_enqueueGlobalWithDeadline_hook_Fn = {
50+
sec,
51+
nsec,
52+
tsec,
53+
tnsec,
54+
clock,
55+
job,
56+
original in
57+
JavaScriptEventLoop.shared.enqueue(job, withDelay: sec, nsec, tsec, tnsec, clock)
58+
}
59+
swift_task_enqueueGlobalWithDeadline_hook = unsafeBitCast(
60+
swift_task_enqueueGlobalWithDeadline_hook_impl,
61+
to: UnsafeMutableRawPointer?.self
62+
)
63+
#endif
64+
65+
typealias swift_task_enqueueMainExecutor_hook_Fn = @convention(thin) (
66+
UnownedJob, swift_task_enqueueMainExecutor_original
67+
) -> Void
68+
let swift_task_enqueueMainExecutor_hook_impl: swift_task_enqueueMainExecutor_hook_Fn = { job, original in
69+
JavaScriptEventLoop.shared.unsafeEnqueue(job)
70+
}
71+
swift_task_enqueueMainExecutor_hook = unsafeBitCast(
72+
swift_task_enqueueMainExecutor_hook_impl,
73+
to: UnsafeMutableRawPointer?.self
74+
)
75+
76+
}
77+
}
78+
79+
80+
#if compiler(>=5.7)
81+
/// Taken from https://github.com/apple/swift/blob/d375c972f12128ec6055ed5f5337bfcae3ec67d8/stdlib/public/Concurrency/Clock.swift#L84-L88
82+
@_silgen_name("swift_get_time")
83+
internal func swift_get_time(
84+
_ seconds: UnsafeMutablePointer<Int64>,
85+
_ nanoseconds: UnsafeMutablePointer<Int64>,
86+
_ clock: CInt
87+
)
88+
89+
@available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)
90+
extension JavaScriptEventLoop {
91+
fileprivate func enqueue(
92+
_ job: UnownedJob,
93+
withDelay seconds: Int64,
94+
_ nanoseconds: Int64,
95+
_ toleranceSec: Int64,
96+
_ toleranceNSec: Int64,
97+
_ clock: Int32
98+
) {
99+
var nowSec: Int64 = 0
100+
var nowNSec: Int64 = 0
101+
swift_get_time(&nowSec, &nowNSec, clock)
102+
let delayNanosec = (seconds - nowSec) * 1_000_000_000 + (nanoseconds - nowNSec)
103+
enqueue(job, withDelay: delayNanosec <= 0 ? 0 : UInt64(delayNanosec))
104+
}
105+
}
106+
#endif
107+

Sources/JavaScriptEventLoop/JavaScriptEventLoop.swift

+3-99
Original file line numberDiff line numberDiff line change
@@ -120,79 +120,11 @@ public final class JavaScriptEventLoop: SerialExecutor, @unchecked Sendable {
120120

121121
@MainActor private static func installGlobalExecutorIsolated() {
122122
guard !didInstallGlobalExecutor else { return }
123-
124-
#if compiler(>=5.9)
125-
typealias swift_task_asyncMainDrainQueue_hook_Fn = @convention(thin) (
126-
swift_task_asyncMainDrainQueue_original, swift_task_asyncMainDrainQueue_override
127-
) -> Void
128-
let swift_task_asyncMainDrainQueue_hook_impl: swift_task_asyncMainDrainQueue_hook_Fn = { _, _ in
129-
swjs_unsafe_event_loop_yield()
130-
}
131-
swift_task_asyncMainDrainQueue_hook = unsafeBitCast(
132-
swift_task_asyncMainDrainQueue_hook_impl,
133-
to: UnsafeMutableRawPointer?.self
134-
)
135-
#endif
136-
137-
typealias swift_task_enqueueGlobal_hook_Fn = @convention(thin) (UnownedJob, swift_task_enqueueGlobal_original)
138-
-> Void
139-
let swift_task_enqueueGlobal_hook_impl: swift_task_enqueueGlobal_hook_Fn = { job, original in
140-
JavaScriptEventLoop.shared.unsafeEnqueue(job)
141-
}
142-
swift_task_enqueueGlobal_hook = unsafeBitCast(
143-
swift_task_enqueueGlobal_hook_impl,
144-
to: UnsafeMutableRawPointer?.self
145-
)
146-
147-
typealias swift_task_enqueueGlobalWithDelay_hook_Fn = @convention(thin) (
148-
UInt64, UnownedJob, swift_task_enqueueGlobalWithDelay_original
149-
) -> Void
150-
let swift_task_enqueueGlobalWithDelay_hook_impl: swift_task_enqueueGlobalWithDelay_hook_Fn = {
151-
delay,
152-
job,
153-
original in
154-
JavaScriptEventLoop.shared.enqueue(job, withDelay: delay)
155-
}
156-
swift_task_enqueueGlobalWithDelay_hook = unsafeBitCast(
157-
swift_task_enqueueGlobalWithDelay_hook_impl,
158-
to: UnsafeMutableRawPointer?.self
159-
)
160-
161-
#if compiler(>=5.7)
162-
typealias swift_task_enqueueGlobalWithDeadline_hook_Fn = @convention(thin) (
163-
Int64, Int64, Int64, Int64, Int32, UnownedJob, swift_task_enqueueGlobalWithDelay_original
164-
) -> Void
165-
let swift_task_enqueueGlobalWithDeadline_hook_impl: swift_task_enqueueGlobalWithDeadline_hook_Fn = {
166-
sec,
167-
nsec,
168-
tsec,
169-
tnsec,
170-
clock,
171-
job,
172-
original in
173-
JavaScriptEventLoop.shared.enqueue(job, withDelay: sec, nsec, tsec, tnsec, clock)
174-
}
175-
swift_task_enqueueGlobalWithDeadline_hook = unsafeBitCast(
176-
swift_task_enqueueGlobalWithDeadline_hook_impl,
177-
to: UnsafeMutableRawPointer?.self
178-
)
179-
#endif
180-
181-
typealias swift_task_enqueueMainExecutor_hook_Fn = @convention(thin) (
182-
UnownedJob, swift_task_enqueueMainExecutor_original
183-
) -> Void
184-
let swift_task_enqueueMainExecutor_hook_impl: swift_task_enqueueMainExecutor_hook_Fn = { job, original in
185-
JavaScriptEventLoop.shared.unsafeEnqueue(job)
186-
}
187-
swift_task_enqueueMainExecutor_hook = unsafeBitCast(
188-
swift_task_enqueueMainExecutor_hook_impl,
189-
to: UnsafeMutableRawPointer?.self
190-
)
191-
123+
installByLegacyHook()
192124
didInstallGlobalExecutor = true
193125
}
194126

195-
private func enqueue(_ job: UnownedJob, withDelay nanoseconds: UInt64) {
127+
internal func enqueue(_ job: UnownedJob, withDelay nanoseconds: UInt64) {
196128
let milliseconds = nanoseconds / 1_000_000
197129
setTimeout(
198130
Double(milliseconds),
@@ -206,7 +138,7 @@ public final class JavaScriptEventLoop: SerialExecutor, @unchecked Sendable {
206138
)
207139
}
208140

209-
private func unsafeEnqueue(_ job: UnownedJob) {
141+
internal func unsafeEnqueue(_ job: UnownedJob) {
210142
#if canImport(wasi_pthread) && compiler(>=6.1) && _runtime(_multithreaded)
211143
guard swjs_get_worker_thread_id_cached() == SWJS_MAIN_THREAD_ID else {
212144
// Notify the main thread to execute the job when a job is
@@ -240,34 +172,6 @@ public final class JavaScriptEventLoop: SerialExecutor, @unchecked Sendable {
240172
}
241173
}
242174

243-
#if compiler(>=5.7)
244-
/// Taken from https://github.com/apple/swift/blob/d375c972f12128ec6055ed5f5337bfcae3ec67d8/stdlib/public/Concurrency/Clock.swift#L84-L88
245-
@_silgen_name("swift_get_time")
246-
internal func swift_get_time(
247-
_ seconds: UnsafeMutablePointer<Int64>,
248-
_ nanoseconds: UnsafeMutablePointer<Int64>,
249-
_ clock: CInt
250-
)
251-
252-
@available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *)
253-
extension JavaScriptEventLoop {
254-
fileprivate func enqueue(
255-
_ job: UnownedJob,
256-
withDelay seconds: Int64,
257-
_ nanoseconds: Int64,
258-
_ toleranceSec: Int64,
259-
_ toleranceNSec: Int64,
260-
_ clock: Int32
261-
) {
262-
var nowSec: Int64 = 0
263-
var nowNSec: Int64 = 0
264-
swift_get_time(&nowSec, &nowNSec, clock)
265-
let delayNanosec = (seconds - nowSec) * 1_000_000_000 + (nanoseconds - nowNSec)
266-
enqueue(job, withDelay: delayNanosec <= 0 ? 0 : UInt64(delayNanosec))
267-
}
268-
}
269-
#endif
270-
271175
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
272176
extension JSPromise {
273177
/// Wait for the promise to complete, returning (or throwing) its result.

0 commit comments

Comments
 (0)