11using System ;
22using System . Collections ;
3- using System . Collections . Generic ;
43using System . Linq ;
4+ using System . Runtime . ExceptionServices ;
55using System . Threading ;
66using System . Threading . Tasks ;
77using NiL . JS . Core ;
@@ -81,11 +81,11 @@ internal Promise(Task<JSValue> task)
8181 {
8282 if ( t . Status == TaskStatus . RanToCompletion )
8383 {
84- handlePromiseCascade ( t . Result ) ;
84+ handlePromiseCascade ( t . Result , false ) ;
8585 }
8686 else if ( t . Status == TaskStatus . Faulted )
8787 {
88- _outerTask . SetException ( t . Exception ) ;
88+ _outerTask . SetException ( t . Exception . GetBaseException ( ) ?? t . Exception ) ;
8989 }
9090 else
9191 {
@@ -109,19 +109,28 @@ internal Promise(Task<JSValue> task)
109109 _innerTask = task . ContinueWith ( continuation ) ;
110110 }
111111
112- private void handlePromiseCascade ( JSValue value )
112+ private void handlePromiseCascade ( JSValue value , bool error )
113113 {
114114 var task = ( value ? . Value as Promise ) ? . Task ?? value ? . Value as Task < JSValue > ;
115115 if ( task != null )
116116 {
117117 task . ContinueWith ( ( t ) =>
118118 {
119- handlePromiseCascade ( t . Result ) ;
119+ if ( t . IsFaulted )
120+ {
121+ var exception = t . Exception . GetBaseException ( ) as JSException ?? t . Exception . GetBaseException ( ) ?? t . Exception ;
122+ _outerTask . SetException ( exception ) ;
123+ }
124+ else
125+ handlePromiseCascade ( t . Result , false ) ;
120126 } ) ;
121127 }
122128 else
123129 {
124- _outerTask . SetResult ( value ) ;
130+ if ( error )
131+ _outerTask . SetException ( new JSException ( value ) ) ;
132+ else
133+ _outerTask . SetResult ( value ) ;
125134 }
126135 }
127136
@@ -139,7 +148,7 @@ private void callbackInvoke()
139148 {
140149 statusSet = true ;
141150
142- handlePromiseCascade ( args [ 0 ] ) ;
151+ handlePromiseCascade ( args [ 0 ] , false ) ;
143152 }
144153
145154 return null ;
@@ -151,7 +160,7 @@ private void callbackInvoke()
151160 {
152161 statusSet = true ;
153162
154- handlePromiseCascade ( args [ 0 ] ) ;
163+ handlePromiseCascade ( args [ 0 ] , true ) ;
155164 }
156165
157166 return null ;
@@ -173,13 +182,20 @@ private void callbackInvoke()
173182 throw ;
174183 }
175184
176- if ( ! statusSet )
177- _outerTask . SetResult ( JSValue . undefined ) ;
185+ // if (!statusSet)
186+ // _outerTask.SetResult(JSValue.undefined);
178187 }
179188
180189 public static Promise resolve ( JSValue data )
181190 {
182- return new Promise ( fromResult ( data ) ) ;
191+ return data . As < Promise > ( ) ?? new Promise ( fromResult ( data ) ) ;
192+ }
193+
194+ public static Promise reject ( JSValue data )
195+ {
196+ var result = new Promise ( ) ;
197+ result . _outerTask . SetException ( new JSException ( data ) ) ;
198+ return result ;
183199 }
184200
185201 public static Promise race ( IIterable promises )
@@ -212,36 +228,50 @@ public Promise then(Function onFulfilment, Function onRejection)
212228 {
213229 return then (
214230 onFulfilment == null ? null : value => onFulfilment . Call ( JSValue . undefined , new Arguments { value } ) ,
215- onRejection == null ? null : value => onRejection . Call ( JSValue . undefined , new Arguments { value } ) ) ;
231+ onRejection == null ? null : value => onRejection . Call ( JSValue . undefined , new Arguments { value } ) ,
232+ false ) ;
233+ }
234+
235+ public Promise @finally ( Function onFinally )
236+ {
237+ Func < JSValue , JSValue > func = onFinally == null ? null : value => onFinally . Call ( JSValue . undefined , new Arguments { value } ) ;
238+ return then ( func , func , true ) ;
216239 }
217240
218241 [ Hidden ]
219- public Promise then ( Func < JSValue , JSValue > onFulfilment , Func < JSValue , JSValue > onRejection )
242+ public Promise then ( Func < JSValue , JSValue > onFulfilment , Func < JSValue , JSValue > onRejection , bool rethrow )
220243 {
221244 if ( onFulfilment == null && onRejection == null )
222245 return resolve ( JSValue . undefined ) ;
223246
224- var thenTask = onFulfilment == null ? null : _outerTask . Task . ContinueWith ( task => onFulfilment ( Result ) , TaskContinuationOptions . OnlyOnRanToCompletion ) ;
225-
226- var catchTask = onRejection == null ? null :
227- _outerTask . Task . ContinueWith ( task =>
247+ var catchTask = onRejection == null
248+ ? null
249+ : _outerTask . Task . ContinueWith ( task =>
228250 {
229- Exception ex = task . Exception ;
230- while ( ex . InnerException != null )
231- ex = ex . InnerException ;
232-
233- var jsException = ex as JSException ;
234- if ( jsException != null )
251+ Exception ex = task . Exception . GetBaseException ( ) ;
252+ JSValue result ;
253+ if ( ex is JSException jsException )
235254 {
236- return onRejection ( jsException . Error ) ;
255+ result = onRejection ( jsException . Error ) ;
237256 }
238257 else
239258 {
240- return onRejection ( Context . CurrentGlobalContext . ProxyValue ( task . Exception . GetBaseException ( ) ) ) ;
259+ result = onRejection ( Context . CurrentGlobalContext . ProxyValue ( ex ) ) ;
241260 }
261+
262+ if ( rethrow )
263+ ExceptionDispatchInfo . Capture ( ex ) . Throw ( ) ;
264+
265+ return result ;
242266 } ,
243267 TaskContinuationOptions . NotOnRanToCompletion ) ;
244268
269+ var thenTask = onFulfilment == null
270+ ? null
271+ : catchTask is not null
272+ ? _outerTask . Task . ContinueWith ( task => onFulfilment ( task . Result ) , TaskContinuationOptions . OnlyOnRanToCompletion )
273+ : _outerTask . Task . ContinueWith ( task => onFulfilment ( task . Result ) ) ;
274+
245275 if ( thenTask != null )
246276 {
247277 if ( catchTask != null )
@@ -308,14 +338,24 @@ private static Task<JSValue[]> whenAll(Task<JSValue>[] tasks)
308338
309339 Action < Task < JSValue > > contination = t =>
310340 {
311- var index = System . Array . IndexOf ( tasks , t ) ;
312- if ( t . IsCanceled )
313- throw new OperationCanceledException ( ) ;
341+ if ( task . Task . IsCompleted )
342+ return ;
314343
315- result [ index ] = t . Result ;
344+ try
345+ {
346+ var index = System . Array . IndexOf ( tasks , t ) ;
347+ if ( t . IsCanceled )
348+ throw new OperationCanceledException ( ) ;
349+
350+ result [ index ] = t . Result ;
316351
317- if ( Interlocked . Decrement ( ref count ) == 0 )
318- task . SetResult ( result ) ;
352+ if ( Interlocked . Decrement ( ref count ) == 0 )
353+ task . SetResult ( result ) ;
354+ }
355+ catch ( Exception e )
356+ {
357+ task . SetException ( e . GetBaseException ( ) ?? e ) ;
358+ }
319359 } ;
320360
321361 for ( var i = 0 ; i < tasks . Length ; i ++ )
0 commit comments