@@ -9,7 +9,7 @@ This doesn't 100% match the JavaScript API, as `then` overload with two callback
9
9
It's impossible to unify success and failure types from both callbacks in a single returned promise
10
10
without type erasure. You should chain `then` and `catch` in those cases to avoid type erasure.
11
11
*/
12
- public final class JSPromise < Success , Failure > : ConvertibleToJSValue , ConstructibleFromJSValue {
12
+ public final class JSPromise : JSBridgedClass {
13
13
/// The underlying JavaScript `Promise` object.
14
14
public let jsObject : JSObject
15
15
@@ -18,17 +18,20 @@ public final class JSPromise<Success, Failure>: ConvertibleToJSValue, Constructi
18
18
. object( jsObject)
19
19
}
20
20
21
+ public static var constructor : JSFunction {
22
+ JSObject . global. Promise. function!
23
+ }
24
+
21
25
/// This private initializer assumes that the passed object is a JavaScript `Promise`
22
- private init ( unsafe object: JSObject ) {
26
+ public init ( unsafelyWrapping object: JSObject ) {
23
27
self . jsObject = object
24
28
}
25
29
26
30
/** Creates a new `JSPromise` instance from a given JavaScript `Promise` object. If `jsObject`
27
31
is not an instance of JavaScript `Promise`, this initializer will return `nil`.
28
32
*/
29
- public init ? ( _ jsObject: JSObject ) {
30
- guard jsObject. isInstanceOf ( JSObject . global. Promise. function!) else { return nil }
31
- self . jsObject = jsObject
33
+ public convenience init ? ( _ jsObject: JSObject ) {
34
+ self . init ( from: jsObject)
32
35
}
33
36
34
37
/** Creates a new `JSPromise` instance from a given JavaScript `Promise` object. If `value`
@@ -40,73 +43,10 @@ public final class JSPromise<Success, Failure>: ConvertibleToJSValue, Constructi
40
43
return Self . init ( jsObject)
41
44
}
42
45
43
- /** Schedules the `success` closure to be invoked on sucessful completion of `self`.
44
- */
45
- public func then( success: @escaping ( ) -> ( ) ) {
46
- let closure = JSOneshotClosure { _ in
47
- success ( )
48
- return . undefined
49
- }
50
- _ = jsObject. then!( closure)
51
- }
52
-
53
- /** Schedules the `failure` closure to be invoked on either successful or rejected completion of
54
- `self`.
55
- */
56
- public func finally( successOrFailure: @escaping ( ) -> ( ) ) -> Self {
57
- let closure = JSOneshotClosure { _ in
58
- successOrFailure ( )
59
- return . undefined
60
- }
61
- return . init( unsafe: jsObject. finally!( closure) . object!)
62
- }
63
- }
64
-
65
- extension JSPromise where Success == ( ) , Failure == Never {
66
- /** Creates a new `JSPromise` instance from a given `resolver` closure. `resolver` takes
67
- a closure that your code should call to resolve this `JSPromise` instance.
68
- */
69
- public convenience init ( resolver: @escaping ( @escaping ( ) -> ( ) ) -> ( ) ) {
70
- let closure = JSOneshotClosure { arguments in
71
- // The arguments are always coming from the `Promise` constructor, so we should be
72
- // safe to assume their type here
73
- resolver { arguments [ 0 ] . function!( ) }
74
- return . undefined
75
- }
76
- self . init ( unsafe: JSObject . global. Promise. function!. new ( closure) )
77
- }
78
- }
79
-
80
- extension JSPromise where Failure: ConvertibleToJSValue {
81
- /** Creates a new `JSPromise` instance from a given `resolver` closure. `resolver` takes
46
+ /** Creates a new `JSPromise` instance from a given `resolver` closure. `resolver` takes
82
47
two closure that your code should call to either resolve or reject this `JSPromise` instance.
83
48
*/
84
- public convenience init ( resolver: @escaping ( @escaping ( Result < Success , JSError > ) -> ( ) ) -> ( ) ) {
85
- let closure = JSOneshotClosure { arguments in
86
- // The arguments are always coming from the `Promise` constructor, so we should be
87
- // safe to assume their type here
88
- let resolve = arguments [ 0 ] . function!
89
- let reject = arguments [ 1 ] . function!
90
-
91
- resolver {
92
- switch $0 {
93
- case . success:
94
- resolve ( )
95
- case let . failure( error) :
96
- reject ( error. jsValue ( ) )
97
- }
98
- }
99
- return . undefined
100
- }
101
- self . init ( unsafe: JSObject . global. Promise. function!. new ( closure) )
102
- }
103
- }
104
-
105
- extension JSPromise where Success: ConvertibleToJSValue , Failure: JSError {
106
- /** Creates a new `JSPromise` instance from a given `resolver` closure. `resolver` takes
107
- a closure that your code should call to either resolve or reject this `JSPromise` instance.
108
- */
109
- public convenience init ( resolver: @escaping ( @escaping ( Result < Success , JSError > ) -> ( ) ) -> ( ) ) {
49
+ public convenience init ( resolver: @escaping ( @escaping ( Result < JSValue , JSValue > ) -> ( ) ) -> ( ) ) {
110
50
let closure = JSOneshotClosure { arguments in
111
51
// The arguments are always coming from the `Promise` constructor, so we should be
112
52
// safe to assume their type here
@@ -116,123 +56,67 @@ extension JSPromise where Success: ConvertibleToJSValue, Failure: JSError {
116
56
resolver {
117
57
switch $0 {
118
58
case let . success( success) :
119
- resolve ( success. jsValue ( ) )
59
+ resolve ( success)
120
60
case let . failure( error) :
121
- reject ( error. jsValue ( ) )
61
+ reject ( error)
122
62
}
123
63
}
124
64
return . undefined
125
65
}
126
- self . init ( unsafe : JSObject . global . Promise . function! . new ( closure) )
66
+ self . init ( unsafelyWrapping : Self . constructor . new ( closure) )
127
67
}
128
- }
129
68
130
- extension JSPromise where Success: ConstructibleFromJSValue {
131
- /** Schedules the `success` closure to be invoked on sucessful completion of `self`.
132
- */
133
- public func then(
134
- success: @escaping ( Success ) -> ( ) ,
135
- file: StaticString = #file,
136
- line: Int = #line
137
- ) {
138
- let closure = JSOneshotClosure { arguments in
139
- guard let result = Success . construct ( from: arguments [ 0 ] ) else {
140
- fatalError ( " \( file) : \( line) : failed to unwrap success value for `then` callback " )
141
- }
142
- success ( result)
143
- return . undefined
144
- }
145
- _ = jsObject. then!( closure)
69
+ public static func resolve( _ value: JSValue ) -> JSPromise {
70
+ self . init ( unsafelyWrapping: Self . constructor. resolve!( value) . object!)
146
71
}
147
72
148
- /** Returns a new promise created from chaining the current `self` promise with the `success`
149
- closure invoked on sucessful completion of `self`. The returned promise will have a new
150
- `Success` type equal to the return type of `success`.
151
- */
152
- public func then< ResultType: ConvertibleToJSValue > (
153
- success: @escaping ( Success ) -> ResultType ,
154
- file: StaticString = #file,
155
- line: Int = #line
156
- ) -> JSPromise < ResultType , Failure > {
157
- let closure = JSOneshotClosure { arguments -> JSValue in
158
- guard let result = Success . construct ( from: arguments [ 0 ] ) else {
159
- fatalError ( " \( file) : \( line) : failed to unwrap success value for `then` callback " )
160
- }
161
- return success ( result) . jsValue ( )
162
- }
163
- return . init( unsafe: jsObject. then!( closure) . object!)
73
+ public static func reject( _ reason: JSValue ) -> JSPromise {
74
+ self . init ( unsafelyWrapping: Self . constructor. reject!( reason) . object!)
164
75
}
165
76
166
- /** Returns a new promise created from chaining the current `self` promise with the `success`
167
- closure invoked on sucessful completion of `self`. The returned promise will have a new type
168
- equal to the return type of `success`.
77
+ /** Schedules the `success` closure to be invoked on sucessful completion of `self`.
169
78
*/
170
- public func then< ResultSuccess: ConvertibleToJSValue , ResultFailure: ConstructibleFromJSValue > (
171
- success: @escaping ( Success ) -> JSPromise < ResultSuccess , ResultFailure > ,
172
- file: StaticString = #file,
173
- line: Int = #line
174
- ) -> JSPromise < ResultSuccess , ResultFailure > {
175
- let closure = JSOneshotClosure { arguments -> JSValue in
176
- guard let result = Success . construct ( from: arguments [ 0 ] ) else {
177
- fatalError ( " \( file) : \( line) : failed to unwrap success value for `then` callback " )
178
- }
179
- return success ( result) . jsValue ( )
79
+ @discardableResult
80
+ public func then( success: @escaping ( JSValue ) -> JSValue ) -> JSPromise {
81
+ let closure = JSOneshotClosure {
82
+ return success ( $0 [ 0 ] )
180
83
}
181
- return . init ( unsafe : jsObject. then!( closure) . object!)
84
+ return JSPromise ( unsafelyWrapping : jsObject. then!( closure) . object!)
182
85
}
183
- }
184
86
185
- extension JSPromise where Failure: ConstructibleFromJSValue {
186
- /** Returns a new promise created from chaining the current `self` promise with the `failure`
187
- closure invoked on rejected completion of `self`. The returned promise will have a new `Success`
188
- type equal to the return type of the callback, while the `Failure` type becomes `Never`.
87
+ /** Schedules the `success` closure to be invoked on sucessful completion of `self`.
189
88
*/
190
- public func `catch`< ResultSuccess: ConvertibleToJSValue > (
191
- failure: @escaping ( Failure ) -> ResultSuccess ,
192
- file: StaticString = #file,
193
- line: Int = #line
194
- ) -> JSPromise < ResultSuccess , Never > {
195
- let closure = JSOneshotClosure { arguments -> JSValue in
196
- guard let error = Failure . construct ( from: arguments [ 0 ] ) else {
197
- fatalError ( " \( file) : \( line) : failed to unwrap error value for `catch` callback " )
198
- }
199
- return failure ( error) . jsValue ( )
89
+ @discardableResult
90
+ public func then( success: @escaping ( JSValue ) -> JSValue ,
91
+ failure: @escaping ( JSValue ) -> JSValue ) -> JSPromise {
92
+ let successClosure = JSOneshotClosure {
93
+ return success ( $0 [ 0 ] )
200
94
}
201
- return . init( unsafe: jsObject. then!( JSValue . undefined, closure) . object!)
95
+ let failureClosure = JSOneshotClosure {
96
+ return failure ( $0 [ 0 ] )
97
+ }
98
+ return JSPromise ( unsafelyWrapping: jsObject. then!( successClosure, failureClosure) . object!)
202
99
}
203
100
204
101
/** Schedules the `failure` closure to be invoked on rejected completion of `self`.
205
102
*/
206
- public func `catch`(
207
- failure: @escaping ( Failure ) -> ( ) ,
208
- file: StaticString = #file,
209
- line: Int = #line
210
- ) {
211
- let closure = JSOneshotClosure { arguments in
212
- guard let error = Failure . construct ( from: arguments [ 0 ] ) else {
213
- fatalError ( " \( file) : \( line) : failed to unwrap error value for `catch` callback " )
214
- }
215
- failure ( error)
216
- return . undefined
103
+ @discardableResult
104
+ public func `catch`( failure: @escaping ( JSValue ) -> JSValue ) -> JSPromise {
105
+ let closure = JSOneshotClosure {
106
+ return failure ( $0 [ 0 ] )
217
107
}
218
- _ = jsObject. then! ( JSValue . undefined , closure)
108
+ return . init ( unsafelyWrapping : jsObject. catch! ( closure) . object! )
219
109
}
220
110
221
- /** Returns a new promise created from chaining the current `self` promise with the `failure`
222
- closure invoked on rejected completion of `self`. The returned promise will have a new type
223
- equal to the return type of `success`.
111
+ /** Schedules the `failure` closure to be invoked on either successful or rejected completion of
112
+ `self`.
224
113
*/
225
- public func `catch`< ResultSuccess: ConvertibleToJSValue , ResultFailure: ConstructibleFromJSValue > (
226
- failure: @escaping ( Failure ) -> JSPromise < ResultSuccess , ResultFailure > ,
227
- file: StaticString = #file,
228
- line: Int = #line
229
- ) -> JSPromise < ResultSuccess , ResultFailure > {
230
- let closure = JSOneshotClosure { arguments -> JSValue in
231
- guard let error = Failure . construct ( from: arguments [ 0 ] ) else {
232
- fatalError ( " \( file) : \( line) : failed to unwrap error value for `catch` callback " )
233
- }
234
- return failure ( error) . jsValue ( )
114
+ @discardableResult
115
+ public func finally( successOrFailure: @escaping ( ) -> ( ) ) -> JSPromise {
116
+ let closure = JSOneshotClosure { _ in
117
+ successOrFailure ( )
118
+ return . undefined
235
119
}
236
- return . init( unsafe : jsObject. then! ( JSValue . undefined , closure) . object!)
120
+ return . init( unsafelyWrapping : jsObject. finally! ( closure) . object!)
237
121
}
238
122
}
0 commit comments