@@ -247,49 +247,6 @@ const defaultMethods = {
247
247
xor : ( [ a , b ] ) => a ^ b ,
248
248
// Why "executeInLoop"? Because if it needs to execute to get an array, I do not want to execute the arguments,
249
249
// Both for performance and safety reasons.
250
- '??' : {
251
- [ Sync ] : ( data , buildState ) => isSyncDeep ( data , buildState . engine , buildState ) ,
252
- method : ( arr , _1 , _2 , engine ) => {
253
- // See "executeInLoop" above
254
- const executeInLoop = Array . isArray ( arr )
255
- if ( ! executeInLoop ) arr = engine . run ( arr , _1 , { above : _2 } )
256
-
257
- let item
258
- for ( let i = 0 ; i < arr . length ; i ++ ) {
259
- item = executeInLoop ? engine . run ( arr [ i ] , _1 , { above : _2 } ) : arr [ i ]
260
- if ( downgrade ( item ) !== null && item !== undefined ) return item
261
- }
262
-
263
- if ( item === undefined ) return null
264
- return item
265
- } ,
266
- asyncMethod : async ( arr , _1 , _2 , engine ) => {
267
- // See "executeInLoop" above
268
- const executeInLoop = Array . isArray ( arr )
269
- if ( ! executeInLoop ) arr = await engine . run ( arr , _1 , { above : _2 } )
270
-
271
- let item
272
- for ( let i = 0 ; i < arr . length ; i ++ ) {
273
- item = executeInLoop ? await engine . run ( arr [ i ] , _1 , { above : _2 } ) : arr [ i ]
274
- if ( downgrade ( item ) !== null && item !== undefined ) return item
275
- }
276
-
277
- if ( item === undefined ) return null
278
- return item
279
- } ,
280
- deterministic : ( data , buildState ) => isDeterministic ( data , buildState . engine , buildState ) ,
281
- compile : ( data , buildState ) => {
282
- if ( ! chainingSupported ) return false
283
- if ( Array . isArray ( data ) && data . length ) {
284
- return `(${ data . map ( ( i , x ) => {
285
- if ( Array . isArray ( i ) || ! i || typeof i !== 'object' || x === data . length - 1 ) return buildString ( i , buildState )
286
- return 'downgrade(' + buildString ( i , buildState ) + ')'
287
- } ) . join ( ' ?? ' ) } )`
288
- }
289
- return `(${ buildString ( data , buildState ) } ).reduce((a,b) => downgrade(a) ?? b, null)`
290
- } ,
291
- traverse : false
292
- } ,
293
250
or : {
294
251
[ Sync ] : ( data , buildState ) => isSyncDeep ( data , buildState . engine , buildState ) ,
295
252
method : ( arr , _1 , _2 , engine ) => {
@@ -326,6 +283,8 @@ const defaultMethods = {
326
283
} ,
327
284
traverse : false
328
285
} ,
286
+ '??' : defineCoalesce ( ) ,
287
+ try : defineCoalesce ( downgrade ) ,
329
288
and : {
330
289
[ Sync ] : ( data , buildState ) => isSyncDeep ( data , buildState . engine , buildState ) ,
331
290
method : ( arr , _1 , _2 , engine ) => {
@@ -719,6 +678,60 @@ const defaultMethods = {
719
678
}
720
679
}
721
680
681
+ /**
682
+ * Defines separate coalesce methods
683
+ */
684
+ function defineCoalesce ( func ) {
685
+ let downgrade
686
+ if ( func ) downgrade = func
687
+ else downgrade = ( a ) => a
688
+
689
+ return {
690
+ [ Sync ] : ( data , buildState ) => isSyncDeep ( data , buildState . engine , buildState ) ,
691
+ method : ( arr , _1 , _2 , engine ) => {
692
+ // See "executeInLoop" above
693
+ const executeInLoop = Array . isArray ( arr )
694
+ if ( ! executeInLoop ) arr = engine . run ( arr , _1 , { above : _2 } )
695
+
696
+ let item
697
+ for ( let i = 0 ; i < arr . length ; i ++ ) {
698
+ item = executeInLoop ? engine . run ( arr [ i ] , _1 , { above : _2 } ) : arr [ i ]
699
+ if ( downgrade ( item ) !== null && item !== undefined ) return item
700
+ }
701
+
702
+ if ( item === undefined ) return null
703
+ return item
704
+ } ,
705
+ asyncMethod : async ( arr , _1 , _2 , engine ) => {
706
+ // See "executeInLoop" above
707
+ const executeInLoop = Array . isArray ( arr )
708
+ if ( ! executeInLoop ) arr = await engine . run ( arr , _1 , { above : _2 } )
709
+
710
+ let item
711
+ for ( let i = 0 ; i < arr . length ; i ++ ) {
712
+ item = executeInLoop ? await engine . run ( arr [ i ] , _1 , { above : _2 } ) : arr [ i ]
713
+ if ( downgrade ( item ) !== null && item !== undefined ) return item
714
+ }
715
+
716
+ if ( item === undefined ) return null
717
+ return item
718
+ } ,
719
+ deterministic : ( data , buildState ) => isDeterministic ( data , buildState . engine , buildState ) ,
720
+ compile : ( data , buildState ) => {
721
+ if ( ! chainingSupported ) return false
722
+ const funcCall = func ? 'downgrade' : ''
723
+ if ( Array . isArray ( data ) && data . length ) {
724
+ return `(${ data . map ( ( i , x ) => {
725
+ if ( Array . isArray ( i ) || ! i || typeof i !== 'object' || x === data . length - 1 ) return buildString ( i , buildState )
726
+ return `${ funcCall } (` + buildString ( i , buildState ) + ')'
727
+ } ) . join ( ' ?? ' ) } )`
728
+ }
729
+ return `(${ buildString ( data , buildState ) } ).reduce((a,b) => ${ funcCall } (a) ?? b, null)`
730
+ } ,
731
+ traverse : false
732
+ }
733
+ }
734
+
722
735
function createArrayIterativeMethod ( name , useTruthy = false ) {
723
736
return {
724
737
deterministic : ( data , buildState ) => {
0 commit comments