GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — JavaScriptKit/Sources/JavaScriptKit/BasicObjects/JSTimer.swift at main · aehlke/JavaScriptKit

Expand file tree

/

JSTimer.swift

Copy path
More file actions
More file actions

Latest commit

 

History

History
History
96 lines (89 loc) · 4.06 KB
/

JSTimer.swift

Copy path

File metadata and controls

96 lines (89 loc) · 4.06 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/// This timer is an abstraction over [`setInterval`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval)
/// / [`clearInterval`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/clearInterval) and
/// [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout)
/// / [`clearTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout)
/// JavaScript functions. It intentionally doesn't match the JavaScript API, as a special care is
/// needed to hold a reference to the timer closure and to call `JSClosure.release()` on it when the
/// timer is deallocated. As a user, you have to hold a reference to a `JSTimer` instance for it to stay
/// valid. The `JSTimer` API is also intentionally trivial, the timer is started right away, and the
/// only way to invalidate the timer is to bring the reference count of the `JSTimer` instance to zero.
/// For invalidation you should either store the timer in an optional property and assign `nil` to it,
/// or deallocate the object that owns the timer.
public final class JSTimer {
enum ClosureStorage {
case oneshot(JSOneshotClosure)
case repeating(JSClosure)
var jsValue: JSValue {
switch self {
case .oneshot(let closure): return closure.jsValue
case .repeating(let closure): return closure.jsValue
}
}
func release() {
switch self {
case .oneshot(let closure):
closure.release()
case .repeating(let closure):
#if JAVASCRIPTKIT_WITHOUT_WEAKREFS
closure.release()
#else
break // no-op
#endif
}
}
}
/// Indicates whether this timer instance calls its callback repeatedly at a given delay.
public let isRepeating: Bool
private let closure: ClosureStorage
/** Node.js and browser APIs are slightly different. `setTimeout`/`setInterval` return an object
in Node.js, while browsers return a number. Fortunately, clearTimeout and clearInterval take
corresponding types as their arguments, and we can store either as JSValue, so we can treat both
cases uniformly.
*/
private let value: JSValue
private let global = JSObject.global
/**
Creates a new timer instance that calls `setInterval` or `setTimeout` JavaScript functions for you
under the hood.
- Parameters:
- millisecondsDelay: the amount of milliseconds before the `callback` closure is executed.
- isRepeating: when `true` the `callback` closure is executed repeatedly at given
`millisecondsDelay` intervals indefinitely until the timer is deallocated.
- callback: the closure to be executed after a given `millisecondsDelay` interval.
*/
public init(millisecondsDelay: Double, isRepeating: Bool = false, callback: @escaping () -> Void) {
if isRepeating {
closure = .repeating(
JSClosure { _ in
callback()
return .undefined
}
)
} else {
closure = .oneshot(
JSOneshotClosure { _ in
callback()
return .undefined
}
)
}
self.isRepeating = isRepeating
if isRepeating {
value = global.setInterval.object!(arguments: [closure.jsValue, millisecondsDelay.jsValue])
} else {
value = global.setTimeout.object!(arguments: [closure.jsValue, millisecondsDelay.jsValue])
}
}
/** Makes a corresponding `clearTimeout` or `clearInterval` call, depending on whether this timer
instance is repeating. The `closure` instance is released manually here, as it is required for
bridged closure instances.
*/
deinit {
if isRepeating {
global.clearInterval.object!(value)
} else {
global.clearTimeout.object!(value)
}
closure.release()
}
}
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.