ig-types 6.24.16 → 6.24.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/Promise.js +295 -275
  2. package/package.json +1 -1
  3. package/test.js +138 -17
package/Promise.js CHANGED
@@ -34,6 +34,253 @@ var generator = require('./generator')
34
34
 
35
35
 
36
36
 
37
+ //---------------------------------------------------------------------
38
+ // XXX EXPERIMENTING...
39
+
40
+ // packed format API...
41
+ //
42
+ // XXX should this be a container or just a set of function???
43
+ // ...for simplicity I'll keep it a stateless set of functions for
44
+ // now, to avoid yet another layer of indirection -- IterablePromise...
45
+ var packed =
46
+ module.packed =
47
+ {
48
+ //
49
+ // pack(<array>)
50
+ // pack(<promise>)
51
+ // -> <packed>
52
+ //
53
+ // <packed> ::=
54
+ // <packed-array>
55
+ // | <packed-promise>
56
+ //
57
+ // <packed-array> ::=
58
+ // [
59
+ // <item>
60
+ // | <items> - array
61
+ // | <promise-item>
62
+ // | <promise-items>,
63
+ // ...
64
+ // ]
65
+ //
66
+ // NOTE: when all promises are expanded the packed array can be unpacked
67
+ // by simply calling .flat()
68
+ // NOTE: if 'types/Array' is imported this will support throwing STOP
69
+ // from the handler.
70
+ // Due to the async nature of promises though the way stops are
71
+ // handled may be unpredictable -- the handlers can be run out
72
+ // of order, as the nested promises resolve and thus throwing
73
+ // stop will stop the handlers not yet run and not the next
74
+ // handlers in sequence.
75
+ //
76
+ // XXX see if we should self-expand promises...
77
+ // XXX migrate these back into InteractivePromise...
78
+ // XXX does this need onerror(..) ???
79
+ pack: function(list){
80
+ var that = this
81
+ // list: promise...
82
+ // XXX should we just test for typeof(list.then) == 'function'???
83
+ if(list instanceof Promise
84
+ // list: async promise...
85
+ || (typeof(list) == 'object'
86
+ && list.then
87
+ && Symbol.asyncIterator in list)){
88
+ return list
89
+ .then(this.pack.bind(this)) }
90
+ // list: generator...
91
+ if(typeof(list) == 'object'
92
+ && !list.map
93
+ && Symbol.iterator in list){
94
+ list = [...list] }
95
+ // list: non-array / non-iterable...
96
+ if(typeof(list.map) != 'function'){
97
+ list = [list].flat() }
98
+ // list: array...
99
+ // XXX should we self-expand this???
100
+ return list
101
+ .map(function(elem){
102
+ // XXX should we expand generators here???
103
+ return elem instanceof Array ?
104
+ [elem]
105
+ // XXX should we just test for .then(..)???
106
+ // XXX should we self-expand this???
107
+ : elem instanceof Promise ?
108
+ elem.then(function(elem){
109
+ return elem instanceof Array ?
110
+ [elem]
111
+ : elem })
112
+ : elem }) },
113
+ //
114
+ // handle(<packed>, <handler>[, <onerror>])
115
+ // -> <packed>
116
+ //
117
+ // XXX revise nested promise handling...
118
+ // ...something like simplify(<packed>) -> <packed> ???
119
+ // XXX STOP_PROMISED_HANDLERS -- TEST
120
+ handle: function(packed, handler, onerror){
121
+ var that = this
122
+ var handlers = [...arguments].slice(1)
123
+
124
+ if(packed instanceof Promise){
125
+ return packed.then(function(packed){
126
+ return that.handle(packed, ...handlers) }) }
127
+
128
+ var handleSTOP = function(err){
129
+ if(err && err === Array.STOP){
130
+ stop = true
131
+ return []
132
+ } else if(err && err instanceof Array.STOP){
133
+ return err.value }
134
+ throw err }
135
+
136
+ var stop = false
137
+ var map = Array.STOP ?
138
+ 'smap'
139
+ : 'map'
140
+ return packed
141
+ // NOTE: we do not need to rapack after this because the handlers
142
+ // will get the correct (unpacked) values and it's their
143
+ // responsibility to pack them if needed...
144
+ // NOTE: this removes the need to handle sub-arrays unless they are
145
+ // in a promise...
146
+ .flat()
147
+ [map](
148
+ function(elem){
149
+ return elem instanceof Promise ?
150
+ elem.then(function(elem){
151
+ if(stop){
152
+ return [] }
153
+ try{
154
+ var has_promise = false
155
+ // NOTE: do the same thing handle(..) does
156
+ // but on a single level, without expanding
157
+ // arrays...
158
+ if(elem instanceof Array){
159
+ var res = elem.map(function(elem){
160
+ var res = elem instanceof Promise ?
161
+ elem.then(function(elem){
162
+ try{
163
+ return !stop ?
164
+ handler(elem)
165
+ : []
166
+ } catch(err){
167
+ return handleSTOP(err) } })
168
+ : handler(elem)
169
+ has_promise = has_promise
170
+ || res instanceof Promise
171
+ return res })
172
+ // non-arrays...
173
+ } else {
174
+ // NOTE: we are wrapping the result in an array to
175
+ // normalize it with the above...
176
+ res = [handler(elem)]
177
+ has_promise = has_promise
178
+ || res[0] instanceof Promise }
179
+
180
+ // compensate for the outer .flat()...
181
+ // NOTE: at this point res is always an array...
182
+ return has_promise ?
183
+ // NOTE: since we are already in a promise
184
+ // grouping things here is not a big
185
+ // deal, however this is needed to link
186
+ // nested promises with the containing
187
+ // promise...
188
+ Promise.all(res)
189
+ .then(function(res){
190
+ return res.flat() })
191
+ : res.flat()
192
+ } catch(err){
193
+ return handleSTOP(err) } })
194
+ : handler(elem) },
195
+ // onerror...
196
+ function(err){
197
+ stop = true
198
+ typeof(onerror) == 'function'
199
+ && onerror(err) }) },
200
+ //
201
+ // unpack(<packed>)
202
+ // -> <array>
203
+ //
204
+ unpack: function(packed){
205
+ if(packed instanceof Promise){
206
+ return packed.then(this.unpack.bind(this)) }
207
+ var input = packed
208
+ // NOTE: we expand promises on the first two levels of the packed
209
+ // list and then flatten the result...
210
+ for(var [i, elem] of Object.entries(packed)){
211
+ // expand promises in lists...
212
+ if(elem instanceof Array){
213
+ for(var e of elem){
214
+ if(e instanceof Promise){
215
+ // copy the input (on demand) list as we'll need to
216
+ // modify it...
217
+ packed === input
218
+ && (packed = packed.slice())
219
+ // NOTE: this will immediately be caught by the
220
+ // Promise condition below...
221
+ elem = packed[i] =
222
+ Promise.all(elem)
223
+ break } } }
224
+ // expand promises...
225
+ if(elem instanceof Promise){
226
+ return Promise.all(packed)
227
+ .then(this.unpack.bind(this)) } }
228
+ // the list is expanded here...
229
+ return packed.flat() },
230
+ }
231
+
232
+
233
+ //
234
+ // itemResolved(<list>, <onupdate>[, <ondone>])
235
+ // itemResolved(<list>, <options>)
236
+ // -> <list>
237
+ //
238
+ // <onupdate>(<elem>, <index>, <list>)
239
+ //
240
+ // <ondone>(<list>)
241
+ //
242
+ // options format:
243
+ // {
244
+ // onupdate: <func>,
245
+ //
246
+ // // optional
247
+ // ondone: <func>,
248
+ // }
249
+ //
250
+ // XXX rename to Promise.each(..) or Promise.eachPromise(..) ???
251
+ var itemResolved =
252
+ module.itemResolved =
253
+ function(list, onupdate, ondone){
254
+ if(typeof(onupdate) != 'function'){
255
+ var {onupdate, ondone} = onupdate }
256
+ typeof(ondone) == 'function'
257
+ && Promise.all(list)
258
+ .then(ondone)
259
+ for(let [i, elem] of Object.entries(list)){
260
+ if(elem instanceof Promise){
261
+ elem.then(function(elem){
262
+ onupdate(elem, i, list) }) } }
263
+ return list }
264
+
265
+ // Like itemResolved(..) but both onupdate and ondone are optional...
266
+ //
267
+ // XXX do not modify the array after this is called and until ondone(..) is called...
268
+ // XXX should this know how to expand things???
269
+ var selfResolve =
270
+ module.selfResolve =
271
+ function(list, onupdate, ondone){
272
+ if(onupdate
273
+ && typeof(onupdate) != 'function'){
274
+ var {onupdate, ondone} = onupdate }
275
+ return itemResolved(list,
276
+ function(elem, i, list){
277
+ list[i] = elem
278
+ typeof(onupdate) == 'function'
279
+ && onupdate(elem, i, list) },
280
+ ondone) }
281
+
282
+
283
+
37
284
  //---------------------------------------------------------------------
38
285
  // Iterable promise...
39
286
  //
@@ -63,6 +310,9 @@ var generator = require('./generator')
63
310
  // XXX add support for async generators...
64
311
  //
65
312
 
313
+ var EMPTY = {doc: 'empty placeholder'}
314
+
315
+
66
316
  var iterPromiseProxy =
67
317
  module.iterPromiseProxy =
68
318
  function(name){
@@ -114,284 +364,45 @@ object.Constructor('IterablePromise', Promise, {
114
364
  // NOTE: these can be useful for debugging and extending...
115
365
  //
116
366
  // pack and oprionally transform/handle an array (sync)...
117
- //
118
- // NOTE: if 'types/Array' is imported this will support throwing STOP
119
- // from the handler.
120
- // Due to the async nature of promises though the way stops are
121
- // handled may be unpredictable -- the handlers can be run out
122
- // of order, as the nested promises resolve and thus throwing
123
- // stop will stop the handlers not yet run and not the next
124
- // handlers in sequence.
125
- // XXX EXPEREMENTAL: STOP...
126
- // XXX ITER can we unwind (sync/async) generators one by one???
127
- /* XXX this repeats part of the functionality of .__handle(..)
128
367
  __pack: function(list, handler=undefined, onerror=undefined){
129
- var that = this
130
- // handle iterator...
131
- // XXX ITER do we unwind the iterator here or wait to unwind later???
132
- if(typeof(list) == 'object'
133
- && Symbol.iterator in list){
134
- if(!onerror){
135
- list = [...list]
136
- // handle errors in input generator...
137
- // NOTE: this does not offer the most control because semantically
138
- // we bust behave in the same manner as <generator>.iter(..)
139
- } else {
140
- var res = []
141
- try{
142
- for(var e of list){
143
- res.push(e) }
144
- }catch(err){
145
- var r = onerror(err)
146
- r !== undefined
147
- && res.push(r) }
148
- list = res } }
149
368
  // handle iterable promise...
150
369
  if(list instanceof IterablePromise){
151
370
  return this.__handle(list.__packed, handler, onerror) }
152
371
  // handle promise / async-iterator...
153
- // XXX ITER do we unwind the iterator here or wait to unwind later???
154
372
  if(typeof(list) == 'object'
155
373
  && Symbol.asyncIterator in list){
156
374
  return list
157
375
  .iter(handler, onerror)
158
376
  .then(function(list){
159
377
  return that.__pack(list) }) }
160
- if(list instanceof Promise){
161
- return list
162
- .then(function(list){
163
- return that.__pack(list, handler, onerror) }) }
164
- // do the work...
165
- // NOTE: packing and handling are mixed here because it's faster
166
- // to do them both on a single list traverse...
167
- var handle = !!handler
168
- handler = handler
169
- ?? function(elem){
170
- return [elem] }
171
- // XXX this repeats .__handle(..), need to unify...
172
- var stop = false
173
- var map = 'map'
174
- var pack = function(){
175
- return [list].flat()
176
- [map](function(elem){
177
- // XXX EXPEREMENTAL...
178
- return elem instanceof IterablePromise ?
179
- (elem.isSync() ?
180
- handler(elem.sync())
181
- // XXX need to handle this but keep it IterablePromise...
182
- : elem.iterthen(handler))
183
- : (elem instanceof SyncPromise
184
- && !(elem.sync() instanceof Promise)) ?
185
- handler(elem.sync())
186
- : elem && elem.then ?
187
- (handleSTOP ?
188
- // stoppable -- need to handle stop async...
189
- elem
190
- .then(function(res){
191
- return !stop ?
192
- handler(res)
193
- : [] })
194
- // NOTE: we are using .catch(..) here
195
- // instead of directly passing the
196
- // error handler to be able to catch
197
- // the STOP from the handler...
198
- .catch(handleSTOP)
199
- // non-stoppable...
200
- : elem.then(handler))
201
- : elem instanceof Array ?
202
- handler(elem)
203
- // NOTE: we keep things that do not need protecting
204
- // from .flat() as-is...
205
- : !handle ?
206
- elem
207
- : handler(elem) }) }
208
- // pack (stoppable)...
209
- if(!!this.constructor.STOP){
210
- map = 'smap'
211
- var handleSTOP = function(err){
212
- // handle stop...
213
- stop = err
214
- if(err === that.constructor.STOP
215
- || err instanceof that.constructor.STOP){
216
- return 'value' in err ?
217
- err.value
218
- : [] }
219
- throw err }
220
- try{
221
- return pack()
222
- }catch(err){
223
- return handleSTOP(err) } }
224
378
 
225
- // pack (non-stoppable)...
226
- return pack() },
227
- // transform/handle packed array (sync, but can return promises in the list)...
228
- __handle: function(list, handler=undefined, onerror=undefined){
229
- var that = this
230
- if(typeof(list) == 'function'){
231
- handler = list
232
- list = this.__packed }
233
- if(!handler){
234
- return list }
235
- // handle promise list...
236
- if(list instanceof Promise){
237
- return list.then(function(list){
238
- return that.__handle(list, handler, onerror) }) }
239
- // do the work...
240
- // NOTE: since each section of the packed .__array is the same
241
- // structure as the input we'll use .__pack(..) to handle
242
- // them, this also keeps all the handling code in one place.
243
- var map = !!this.constructor.STOP ?
244
- 'smap'
245
- : 'map'
246
- return list[map](function(elem){
247
- elem = elem instanceof Array
248
- || elem instanceof Promise ?
249
- that.__pack(elem, handler, onerror)
250
- : [handler(elem)]
251
- elem = elem instanceof Promise ?
252
- elem.then(function([e]){
253
- return e })
254
- : elem
255
- return elem })
256
- .flat() },
257
- /*/
258
- __pack: function(list, handler=undefined, onerror=undefined){
259
- var that = this
260
- // handle iterator...
261
- // XXX ITER do we unwind the iterator here or wait to unwind later???
262
- if(typeof(list) == 'object'
263
- && Symbol.iterator in list){
264
- if(!onerror){
265
- list = [...list]
266
- // handle errors in input generator...
267
- // NOTE: this does not offer the most control because semantically
268
- // we bust behave in the same manner as <generator>.iter(..)
269
- } else {
270
- var res = []
271
- try{
272
- for(var e of list){
273
- res.push(e) }
274
- }catch(err){
275
- var r = onerror(err)
276
- r !== undefined
277
- && res.push(r) }
278
- list = res } }
279
- // handle iterable promise...
280
- if(list instanceof IterablePromise){
281
- return this.__handle(list.__packed, handler, onerror) }
282
- // handle promise / async-iterator...
283
- // XXX ITER do we unwind the iterator here or wait to unwind later???
284
- if(typeof(list) == 'object'
285
- && Symbol.asyncIterator in list){
286
- return list
287
- .iter(handler, onerror)
288
- .then(function(list){
289
- return that.__pack(list) }) }
290
- if(list instanceof Promise){
291
- return list
292
- .then(function(list){
293
- return that.__pack(list, handler, onerror) }) }
294
- // pack...
295
- list = [list].flat()
296
- .map(function(elem){
297
- return elem instanceof Array ?
298
- [elem]
299
- : elem instanceof Promise ?
300
- elem.then(function(e){
301
- return [e] })
302
- : elem })
379
+ // do the packing...
380
+ var packed = module.packed.pack(list)
303
381
  // handle if needed...
304
382
  return handler ?
305
- this.__handle(list, handler, onerror)
306
- : list },
383
+ this.__handle(packed, handler, onerror)
384
+ : packed },
307
385
  // transform/handle packed array (sync, but can return promises in the list)...
308
- // XXX need a strict spec...
309
- __handle: function(list, handler=undefined, onerror=undefined){
386
+ __handle: function(packed, handler=undefined, onerror=undefined){
310
387
  var that = this
311
- if(typeof(list) == 'function'){
312
- handler = list
313
- list = this.__packed }
388
+ // do .__handle(<func>)
389
+ if(typeof(packed) == 'function'){
390
+ handler = packed
391
+ packed = this.__packed }
314
392
  if(!handler){
315
- return list }
316
- // handle promise list...
317
- if(list instanceof Promise){
318
- return list.then(function(list){
319
- return that.__handle(list, handler, onerror) }) }
320
- // do the work...
321
- list = list instanceof Array ?
322
- list
323
- : [list]
324
- var map = !!this.constructor.STOP ?
325
- 'smap'
326
- : 'map'
327
- var stop = false
328
- // XXX do we handle generators here???
329
- var each = function(elem){
330
- return elem instanceof Array ?
331
- elem
332
- .map(handler)
333
- .flat()
334
- : handler(elem) }
335
- return list
336
- [map](
337
- function(elem){
338
- // NOTE: we are calling .flat() on the result so we
339
- // need to keep a handled array as a single
340
- // element by wrapping the return of handled(..)...
341
- return elem instanceof IterablePromise ?
342
- (elem.isSync() ?
343
- each(elem.sync())
344
- : elem.iterthen(each))
345
- // sync sync promise...
346
- : (elem instanceof SyncPromise
347
- && !(elem.sync() instanceof Promise)) ?
348
- [each(elem.sync())]
349
- // promise / promise-like...
350
- : elem && elem.then ?
351
- // NOTE: when this is explicitly stopped we
352
- // do not call any more handlers after
353
- // STOP is thrown/returned...
354
- // NOTE: the promise protects this from .flat()
355
- elem.then(function(elem){
356
- return !stop ?
357
- each(elem)
358
- : [] })
359
- : elem instanceof Array ?
360
- [each(elem)]
361
- : each(elem) },
362
- // handle STOP...
363
- function(){
364
- stop = true })
365
- .flat() },
366
- //*/
367
- // XXX this should return IterablePromise if .__packed is partially sync (???)
393
+ return packed }
394
+ return module.packed.handle(packed, ...[...arguments].slice(1)) },
368
395
  // unpack array (sync/async)...
369
- __unpack: function(list){
370
- list = list
396
+ __unpack: function(packed){
397
+ // do .__unpack()
398
+ packed = packed
371
399
  ?? this.__packed
372
400
  // handle promise list...
373
- if(list instanceof IterablePromise){
374
- return list.__unpack() }
375
- if(list instanceof Promise){
376
- return list
377
- .then(this.__unpack.bind(this)) }
378
- var res = []
379
- for(var e of list){
380
- if(e instanceof IterablePromise){
381
- e = e.__unpack() }
382
- if(e instanceof SyncPromise){
383
- e = e.sync() }
384
- // give up on a sync solution...
385
- if(e instanceof Promise){
386
- // XXX can we return an IterablePromise???
387
- // XXX is there a more elegant way to do this???
388
- return Promise.all(list)
389
- .then(function(list){
390
- return list.flat() })
391
- .iter() }
392
- res.push(e) }
393
- return res.flat() },
394
-
401
+ if(packed instanceof IterablePromise){
402
+ return packed.__unpack() }
403
+ return module.packed.unpack(packed) },
404
+
405
+
395
406
  [Symbol.asyncIterator]: async function*(){
396
407
  var list = this.__packed
397
408
  if(list instanceof Promise){
@@ -415,22 +426,19 @@ object.Constructor('IterablePromise', Promise, {
415
426
  map: function(func){
416
427
  return this.constructor(this,
417
428
  function(e){
418
- var res = func(e)
419
- return res instanceof Promise ?
420
- res.then(function(e){
421
- return [e] })
422
- : [res] }) },
429
+ return [func(e)] }) },
423
430
  filter: function(func){
424
431
  return this.constructor(this,
425
432
  function(e){
426
433
  var res = func(e)
427
- var _filter = function(elem){
428
- return res ?
429
- [elem]
430
- : [] }
431
434
  return res instanceof Promise ?
432
- res.then(_filter)
433
- : _filter(e) }) },
435
+ res.then(function(res){
436
+ return res ?
437
+ [e]
438
+ : [] })
439
+ : res ?
440
+ [e]
441
+ : [] }) },
434
442
  // NOTE: this does not return an iterable promise as we can't know
435
443
  // what the user reduces to...
436
444
  // NOTE: the items can be handled out of order because the nested
@@ -756,6 +764,7 @@ object.Constructor('IterablePromise', Promise, {
756
764
  // NOTE: if 'types/Array' is imported this will support throwing STOP,
757
765
  // for more info see notes for .__pack(..)
758
766
  // XXX EXPEREMENTAL: STOP...
767
+ // XXX use selfResolve(..)
759
768
  __new__: function(_, list, handler=undefined, onerror=undefined){
760
769
  // instance...
761
770
  var promise
@@ -803,12 +812,16 @@ object.Constructor('IterablePromise', Promise, {
803
812
  list instanceof Promise ?
804
813
  list.then(function(list){
805
814
  obj.__packed = list })
815
+ /*/ XXX use selfResolve(..)
816
+ : selfResolve(list) }
817
+ /*/
806
818
  : list.forEach(function(elem, i){
807
819
  elem instanceof Promise
808
820
  && elem.then(function(elem){
809
821
  lst = obj.__packed.slice()
810
822
  lst[i] = elem
811
823
  obj.__packed = lst }) }) }
824
+ //*/
812
825
  return obj },
813
826
  })
814
827
 
@@ -816,6 +829,7 @@ object.Constructor('IterablePromise', Promise, {
816
829
 
817
830
  //---------------------------------------------------------------------
818
831
  // XXX EXPEREMENTAL/HACK...
832
+ // Sequential iterable promise...
819
833
 
820
834
  // This like IterablePromise but guarantees handler execution in order
821
835
  // element occurrence.
@@ -827,7 +841,7 @@ object.Constructor('IterablePromise', Promise, {
827
841
  // Promise.iter([ .. ]).iter(func)
828
842
  // - func per element
829
843
  // - func is called when an element is resolved/ready
830
- // in any order
844
+ // in order of resolution/readiness
831
845
  // Promise.seqiter([ .. ]).iter(func)
832
846
  // - func per element
833
847
  // - func is called when an element is resolved/ready
@@ -836,6 +850,13 @@ object.Constructor('IterablePromise', Promise, {
836
850
  // NOTE: that here a promise will block handling of later promises even
837
851
  // if they are resolved before it.
838
852
  //
853
+ // XXX is this correct???
854
+ // > g = function*(){ yield* [1,2,3] }
855
+ // // XXX should this expand the generator???
856
+ // > await Promise.seqiter([0, g()])
857
+ // -> [ 0, Object [Generator] {} ]
858
+ // > await Promise.seqiter([0, g()]).flat()
859
+ // -> [ 0, 1, 2, 3 ]
839
860
  // XXX check if this behaves correctly (call order) on concatenation and
840
861
  // other methods...
841
862
  // XXX not sure if this is a viable strategy....
@@ -848,13 +869,14 @@ object.Constructor('IterableSequentialPromise', IterablePromise, {
848
869
  var repack = function(list){
849
870
  var res = []
850
871
  for(var [i, e] of list.entries()){
851
- // XXX check for .then(..) instead???
852
- //if(e instanceof Promise
853
872
  if(e.then
854
873
  // skip last promise -- nothing to wrap...
855
874
  && i < list.length-1){
856
875
  res.push(e
857
876
  .then(function(e){
877
+ // NOTE: this does not call any handlers, thus
878
+ // there should be no risk of out of order
879
+ // handler execution....
858
880
  return seqiter(
859
881
  [e, ...list.slice(i+1)])
860
882
  .flat() }))
@@ -867,14 +889,12 @@ object.Constructor('IterableSequentialPromise', IterablePromise, {
867
889
  list = list instanceof SyncPromise ?
868
890
  list.sync()
869
891
  : list
892
+ // repack...
870
893
  list = list instanceof Array ?
871
894
  repack(list)
872
- // XXX check for .then(..) instead???
873
- //: list instanceof Promise ?
874
895
  : list.then ?
875
896
  list.then(repack)
876
897
  : list
877
-
878
898
  return handler ?
879
899
  this.__handle(list, handler, onerror)
880
900
  : list },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ig-types",
3
- "version": "6.24.16",
3
+ "version": "6.24.18",
4
4
  "description": "Generic JavaScript types and type extensions...",
5
5
  "main": "main.js",
6
6
  "scripts": {
package/test.js CHANGED
@@ -112,9 +112,9 @@ var cases = test.Cases({
112
112
  },
113
113
 
114
114
  IterablePromise: test.TestSet(function(){
115
- var create = function(assert, value){
115
+ var create = function(assert, value, expected){
116
116
  return {
117
- input: value,
117
+ input: expected ?? value,
118
118
  output: assert(Promise.iter(value), 'Promise.iter(', value, ')'),
119
119
  } }
120
120
 
@@ -136,21 +136,17 @@ var cases = test.Cases({
136
136
  array_mixed: function(assert){
137
137
  return create(assert, [1, Promise.resolve(2), 3]) },
138
138
  nested_array_mixed: function(assert){
139
- return create(assert, [
140
- 1,
141
- Promise.resolve(2),
142
- [3],
143
- Promise.resolve([4]),
144
- ]) },
139
+ return create(assert,
140
+ [1, Promise.resolve(2), [3], Promise.resolve([4])],
141
+ [1, 2, [3], [4]]) },
145
142
  promise_array_mixed: function(assert){
146
- return create(assert, Promise.resolve([1, Promise.resolve(2), 3])) },
143
+ return create(assert,
144
+ Promise.resolve([1, Promise.resolve(2), 3]),
145
+ [1, 2, 3]) },
147
146
  promise_nested_array_mixed: function(assert){
148
- return create(assert, Promise.resolve([
149
- 1,
150
- Promise.resolve(2),
151
- [3],
152
- Promise.resolve([4]),
153
- ])) },
147
+ return create(assert,
148
+ Promise.resolve([1, Promise.resolve(2), [3], Promise.resolve([4])]),
149
+ [1, 2, [3], [4]]) },
154
150
  })
155
151
  this.Modifier({
156
152
  nest: function(assert, setup){
@@ -182,6 +178,19 @@ var cases = test.Cases({
182
178
  output: setup.output
183
179
  .filter(function(e){ return false }),
184
180
  } },
181
+ filter_promise_all: function(assert, setup){
182
+ setup.output = setup.output
183
+ .filter(function(e){
184
+ return Promise.resolve(true) })
185
+ return setup },
186
+ filter_promise_none: function(assert, setup){
187
+ return {
188
+ input: [],
189
+ output: setup.output
190
+ .filter(function(e){
191
+ return Promise.resolve(false) }),
192
+ } },
193
+ //*/
185
194
 
186
195
  /* XXX need tuning...
187
196
  concat_basic: function(assert, {input, output}){
@@ -300,6 +309,118 @@ var cases = test.Cases({
300
309
  [1,2,3],
301
310
  'flat unpack', meth)
302
311
  }
312
+
313
+ var order = []
314
+ await Promise.seqiter([
315
+ 1,
316
+ Promise.resolve(2),
317
+ Promise.all([3,4]),
318
+ Promise.seqiter([5]),
319
+ 6,
320
+ ])
321
+ .flat()
322
+ .map(function(e){
323
+ order.push(e)
324
+ return e })
325
+ assert.array(
326
+ order,
327
+ [1,2,3,4,5,6],
328
+ 'Promise.seqiter(..) handle order')
329
+
330
+
331
+ var test_async_handler = async function(input, output, handler, msg){
332
+ // sanity check...
333
+ assert.array(
334
+ await Promise.iter(input, handler),
335
+ output,
336
+ msg+' (sanity check -- fix first)')
337
+ assert.array(
338
+ await Promise.iter(input,
339
+ function(e){
340
+ return Promise.resolve(handler(e)) }),
341
+ await Promise.iter(input, handler),
342
+ msg) }
343
+
344
+ await test_async_handler(
345
+ [
346
+ 1,
347
+ [2],
348
+ Promise.resolve(3),
349
+ Promise.resolve([4]),
350
+ ],
351
+ [],
352
+ function(e){
353
+ return [] },
354
+ 'handler returns promise (empty)')
355
+ await test_async_handler(
356
+ [
357
+ 1,
358
+ [2],
359
+ Promise.resolve(3),
360
+ Promise.resolve([4]),
361
+ ],
362
+ [ 'moo', 'moo', 'moo', 'moo' ],
363
+ function(e){
364
+ return ['moo'] },
365
+ 'handler returns promise (array)')
366
+ await test_async_handler(
367
+ [
368
+ 1,
369
+ [2],
370
+ Promise.resolve(3),
371
+ Promise.resolve([4]),
372
+ ],
373
+ [ ['moo'], ['moo'], ['moo'], ['moo'] ],
374
+ function(e){
375
+ return [['moo']] },
376
+ 'handler returns promise (array-array)')
377
+
378
+ // test STOP...
379
+ assert.array(
380
+ await Promise.iter([1,2,3,4], function(e){
381
+ if(e == 3){
382
+ throw Array.STOP }
383
+ return e }),
384
+ [1,2],
385
+ '.iter(..): STOP: basic')
386
+ assert.array(
387
+ await Promise.iter([1,2,Promise.resolve(3),4], function(e){
388
+ if(e == 3){
389
+ throw Array.STOP }
390
+ return e }),
391
+ // NOTE: 4 here is present as it was handled before the promise resolved...
392
+ [1,2,4],
393
+ '.iter(..): STOP: delayed')
394
+ assert.array(
395
+ await Promise.iter([1,2,Promise.resolve(3),4], function(e){
396
+ if(e == 3){
397
+ throw Array.STOP('stop') }
398
+ return e }),
399
+ // NOTE: 4 here is present as it was handled before the promise resolved...
400
+ [1,2,'stop',4],
401
+ '.iter(..): STOP(..): delayed')
402
+ assert.array(
403
+ await Promise.seqiter([1,2,3,4], function(e){
404
+ if(e == 3){
405
+ throw Array.STOP }
406
+ return e }),
407
+ [1,2],
408
+ '.seqiter(..): STOP: basic')
409
+ assert.array(
410
+ await Promise.seqiter([1,2,Promise.resolve(3),4], function(e){
411
+ if(e == 3){
412
+ throw Array.STOP }
413
+ return e }),
414
+ [1,2],
415
+ '.seqiter(..): STOP: delayed')
416
+ assert.array(
417
+ await Promise.seqiter([1,2,Promise.resolve(3),4], function(e){
418
+ if(e == 3){
419
+ throw Array.STOP('stop') }
420
+ return e }),
421
+ // NOTE: 4 here is present as it was handled before the promise resolved...
422
+ [1,2,'stop'],
423
+ '.seqiter(..): STOP(..): delayed')
303
424
  },
304
425
 
305
426
  // Date.js
@@ -557,8 +678,8 @@ Events.cases({
557
678
 
558
679
 
559
680
  // test event list...
560
- assert.array(obj.events, ['event', 'eventBlank'], '.events')
561
- assert.array(obj.eventful, ['bareEvent', 'bareEventBlank'], '.eventful')
681
+ assert.array(obj.events, ['eventBlank', 'event'], '.events')
682
+ assert.array(obj.eventful, ['bareEventBlank', 'bareEvent'], '.eventful')
562
683
 
563
684
  // bind...
564
685
  var bind = function(evt){