ig-types 6.24.23 → 6.25.0

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 +106 -86
  2. package/package.json +1 -1
  3. package/test.js +45 -0
package/Promise.js CHANGED
@@ -163,8 +163,8 @@ module.packed =
163
163
  return that.handle(packed, ...handlers) }) }
164
164
 
165
165
  var handleSTOP = function(err){
166
+ stop = true
166
167
  if(err && err === Array.STOP){
167
- stop = true
168
168
  return []
169
169
  } else if(err && err instanceof Array.STOP){
170
170
  return err.value }
@@ -174,66 +174,78 @@ module.packed =
174
174
  var map = Array.STOP ?
175
175
  'smap'
176
176
  : 'map'
177
- return packed
178
- // NOTE: we do not need to rapack after this because the handlers
179
- // will get the correct (unpacked) values and it's their
180
- // responsibility to pack them if needed...
181
- // NOTE: this removes the need to handle sub-arrays unless they are
182
- // in a promise...
183
- .flat()
184
- [map](
185
- function(elem){
186
- return elem instanceof Promise ?
187
- elem.then(function(elem){
188
- if(stop){
189
- return [] }
190
- try{
191
- var has_promise = false
192
- // NOTE: do the same thing handle(..) does
193
- // but on a single level, without expanding
194
- // arrays...
195
- if(elem instanceof Array){
196
- var res = elem.map(function(elem){
197
- var res = elem instanceof Promise ?
198
- elem.then(function(elem){
199
- try{
200
- return !stop ?
201
- handler(elem)
202
- : []
203
- } catch(err){
204
- return handleSTOP(err) } })
205
- : handler(elem)
206
- has_promise = has_promise
207
- || res instanceof Promise
208
- return res })
209
- // non-arrays...
210
- } else {
211
- // NOTE: we are wrapping the result in an array to
212
- // normalize it with the above...
213
- res = [handler(elem)]
214
- has_promise = has_promise
215
- || res[0] instanceof Promise }
216
-
217
- // compensate for the outer .flat()...
218
- // NOTE: at this point res is always an array...
219
- return has_promise ?
220
- // NOTE: since we are already in a promise
221
- // grouping things here is not a big
222
- // deal, however this is needed to link
223
- // nested promises with the containing
224
- // promise...
225
- Promise.all(res)
226
- .then(function(res){
227
- return res.flat() })
228
- : res.flat()
229
- } catch(err){
230
- return handleSTOP(err) } })
231
- : handler(elem) },
232
- // onerror...
233
- function(err){
234
- stop = true
235
- typeof(onerror) == 'function'
236
- && onerror(err) }) },
177
+ try{
178
+ return packed
179
+ // NOTE: we do not need to rapack after this because the handlers
180
+ // will get the correct (unpacked) values and it's their
181
+ // responsibility to pack them if needed...
182
+ // NOTE: this removes the need to handle sub-arrays unless they are
183
+ // in a promise...
184
+ .flat()
185
+ [map](
186
+ function(elem){
187
+ return elem instanceof Promise ?
188
+ elem
189
+ .then(function(elem){
190
+ if(stop){
191
+ return [] }
192
+ try{
193
+ var has_promise = false
194
+ // NOTE: do the same thing handle(..) does
195
+ // but on a single level, without expanding
196
+ // arrays...
197
+ if(elem instanceof Array){
198
+ var res = elem
199
+ .map(function(elem){
200
+ var res = elem instanceof Promise ?
201
+ elem.then(function(elem){
202
+ try{
203
+ return !stop ?
204
+ handler(elem)
205
+ : []
206
+ }catch(err){
207
+ return handleSTOP(err) } })
208
+ : handler(elem)
209
+ has_promise = has_promise
210
+ || res instanceof Promise
211
+ return res })
212
+ // non-arrays...
213
+ } else {
214
+ // NOTE: we are wrapping the result in an array to
215
+ // normalize it with the above...
216
+ res = [handler(elem)]
217
+ has_promise = has_promise
218
+ || res[0] instanceof Promise }
219
+
220
+ // compensate for the outer .flat()...
221
+ // NOTE: at this point res is always an array...
222
+ return has_promise ?
223
+ // NOTE: since we are already in a promise
224
+ // grouping things here is not a big
225
+ // deal, however this is needed to link
226
+ // nested promises with the containing
227
+ // promise...
228
+ Promise.all(res)
229
+ .then(function(res){
230
+ return res.flat() })
231
+ : res.flat()
232
+ } catch(err){
233
+ return handleSTOP(err) } })
234
+ // err...
235
+ .catch(function(err){
236
+ stop = true
237
+ typeof(onerror) == 'function'
238
+ && onerror(err)
239
+ return [] })
240
+ : handler(elem) })
241
+ }catch(err){
242
+ // err
243
+ if(err !== Array.STOP
244
+ && !(err instanceof Array.STOP)
245
+ && typeof(onerror) == 'function'){
246
+ onerror(err)
247
+ return [] }
248
+ throw err } },
237
249
  //
238
250
  // unpack(<packed>)
239
251
  // -> <array>
@@ -822,12 +834,17 @@ object.Constructor('IterablePromise', Promise, {
822
834
 
823
835
  // populate new instance...
824
836
  if(promise){
837
+ // handle onerror(..)
838
+ var handleError = function(err){
839
+ onerror ?
840
+ promise.resolve(onerror(err))
841
+ : promise.reject(err) }
825
842
  // handle/pack input data...
826
843
  if(handler != 'raw'){
827
844
  //list = list instanceof IterablePromise ?
828
845
  list = list instanceof this.constructor ?
829
- obj.__handle(list.__packed, handler, onerror)
830
- : obj.__pack(list, handler, onerror) }
846
+ obj.__handle(list.__packed, handler, handleError)
847
+ : obj.__pack(list, handler, handleError) }
831
848
  Object.defineProperty(obj, '__packed', {
832
849
  value: list,
833
850
  enumerable: false,
@@ -944,27 +961,30 @@ object.Constructor('IterableSequentialStartPromise', IterablePromise, {
944
961
 
945
962
 
946
963
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
947
- // XXX might also be a good idea to implement a version of the above to
948
- // handle the next element only after the promise returned by the
949
- // previous handler is resolved -- depth first...
950
- // ...this would help prevent the await execution uncertainty, i.e.:
951
- // console.log(1)
952
- // // note that we are NOTE await'ing for the function here...
953
- // (async function f(){
954
- // console.log(2)})()
955
- // console.log(3)
956
- // -> prints 1, 2, 3
957
- // and:
958
- // console.log(1)
959
- // (async function f(){
960
- // // note the await -- this is the only difference...
961
- // console.log(await 2)})()
962
- // console.log(3)
963
- // -> prints 1, 3, 2
964
- // this is bad because of a handler has two execution paths one with
965
- // an await and one without the order of actual handler execution can
966
- // not be controlled unless we wait for the whole thing to resolve...
967
- //
964
+ // Like IterableSequentialStartPromise(..) but each handler will be
965
+ // called after the previous handler's return value is resolved (if it
966
+ // is a promise).
967
+ //
968
+ // This is needed to control the "unpredictable" behavior of await's in
969
+ // JavaScript, here is a trivial example with an async function starting
970
+ // as if it was sync and as a promise on the next execution frame:
971
+ // console.log(1)
972
+ // // note that we are NOTE await'ing for the function here...
973
+ // (async function f(){
974
+ // console.log(2)})()
975
+ // console.log(3)
976
+ // -> prints 1, 2, 3
977
+ // and:
978
+ // console.log(1)
979
+ // (async function f(){
980
+ // // note the await -- this is the only difference...
981
+ // console.log(await 2)})()
982
+ // console.log(3)
983
+ // -> prints 1, 3, 2
984
+ // this is bad because if a handler has two execution paths one with
985
+ // an await and one without the order of actual handler execution can
986
+ // not be controlled predictably unless we wait for the whole thing to
987
+ // resolve...
968
988
  var IterableSequentialPromise =
969
989
  module.IterableSequentialPromise =
970
990
  object.Constructor('IterableSequentialPromise', IterableSequentialStartPromise, {
@@ -1327,8 +1347,8 @@ object.Mixin('PromiseMixin', 'soft', {
1327
1347
  // XXX should we just check for .then(..) ???
1328
1348
  // XXX update README if this changes...
1329
1349
  : (data.length == 1
1330
- && Symbol.asyncIterator in data[0]
1331
- && 'then' in data[0]) ?
1350
+ && data[0][Symbol.asyncIterator]
1351
+ && data[0].then) ?
1332
1352
  data[0].then(func, ...error)
1333
1353
  : error.length > 0 ?
1334
1354
  function(){
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ig-types",
3
- "version": "6.24.23",
3
+ "version": "6.25.0",
4
4
  "description": "Generic JavaScript types and type extensions...",
5
5
  "main": "main.js",
6
6
  "scripts": {
package/test.js CHANGED
@@ -451,6 +451,51 @@ var cases = test.Cases({
451
451
  '.seqiter(..): STOP(..): delayed')
452
452
 
453
453
  // XXX test .seqstartiter(..)
454
+
455
+
456
+
457
+ // error...
458
+ for(var iter of ['iter', 'seqiter', 'seqstartiter']){
459
+ assert(
460
+ await Promise[iter]([1,2,Promise.resolve(3),4,5],
461
+ function(e){
462
+ if(e == 2){
463
+ throw 'ERROR' }
464
+ return e })
465
+ .catch(function(err){
466
+ return 'done' })
467
+ == 'done',
468
+ `.${iter}(..): .catch(..)`)
469
+ assert(
470
+ await Promise[iter]([1,2,Promise.resolve(3),4,5],
471
+ function(e){
472
+ if(e == 2){
473
+ throw 'ERROR' }
474
+ return e },
475
+ function(err){
476
+ return 'done' })
477
+ == 'done',
478
+ `.${iter}(..): onerror(..)`)
479
+ assert(
480
+ await Promise[iter]([1,2,Promise.resolve(3),4,5],
481
+ function(e){
482
+ if(e == 3){
483
+ throw 'ERROR' }
484
+ return e },
485
+ function(err){
486
+ return 'done' })
487
+ == 'done',
488
+ `.${iter}(..): edge onerror(..)`)
489
+ assert(
490
+ await Promise[iter]([1,2,Promise.resolve(3),4,5],
491
+ function(e){
492
+ if(e == 4){
493
+ throw 'ERROR' }
494
+ return e },
495
+ function(err){
496
+ return 'done' })
497
+ == 'done',
498
+ `.${iter}(..): late onerror(..)`) }
454
499
  },
455
500
 
456
501
  // Date.js