ig-types 6.12.1 → 6.13.6

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 +130 -79
  2. package/package.json +1 -1
  3. package/test.js +143 -28
package/Promise.js CHANGED
@@ -58,6 +58,7 @@ object.Constructor('IterablePromise', Promise, {
58
58
  //
59
59
  // Format:
60
60
  // [
61
+ // <non-array-value>,
61
62
  // [ <value> ],
62
63
  // <promise>,
63
64
  // ...
@@ -65,6 +66,74 @@ object.Constructor('IterablePromise', Promise, {
65
66
  //
66
67
  __list: null,
67
68
 
69
+ // low-level .__list handlers/helpers...
70
+ //
71
+ // NOTE: these can be useful for debugging and extending...
72
+ __pack: function(list, handler){
73
+ var that = this
74
+ // handle iterable promise list...
75
+ if(list instanceof IterablePromise){
76
+ return this.__handle(list.__list, handler) }
77
+ // handle promise list...
78
+ if(list instanceof Promise){
79
+ return list.then(function(list){
80
+ return that.__pack(list, handler) }) }
81
+ // do the work...
82
+ // NOTE: packing and handling are mixed here because it's faster
83
+ // to do them both on a single list traverse...
84
+ var handle = !!handler
85
+ handler = handler
86
+ ?? function(elem){
87
+ return [elem] }
88
+ return [list].flat()
89
+ .map(function(elem){
90
+ return elem && elem.then ?
91
+ //that.__pack(elem, handler)
92
+ elem.then(handler)
93
+ : elem instanceof Array ?
94
+ handler(elem)
95
+ // NOTE: we keep things that do not need protecting
96
+ // from .flat() as-is...
97
+ : !handle ?
98
+ elem
99
+ : handler(elem) }) },
100
+ __handle: function(list, handler){
101
+ var that = this
102
+ if(typeof(list) == 'function'){
103
+ handler = list
104
+ list = this.__list }
105
+ if(!handler){
106
+ return list }
107
+ // handle promise list...
108
+ if(list instanceof Promise){
109
+ return list.then(function(list){
110
+ return that.__handle(list, handler) }) }
111
+ // do the work...
112
+ // NOTE: since each section of the packed .__array is the same
113
+ // structure as the input we'll use .__pack(..) to handle
114
+ // them, this also keeps all the handling code in one place.
115
+ return list.map(function(elem){
116
+ return elem instanceof Array ?
117
+ that.__pack(elem, handler)
118
+ : elem instanceof Promise ?
119
+ that.__pack(elem, handler)
120
+ .then(function(elem){
121
+ return elem.flat() })
122
+ : [handler(elem)] })
123
+ .flat() },
124
+ __unpack: function(list){
125
+ list = list
126
+ ?? this.__list
127
+ // handle promise list...
128
+ if(list instanceof Promise){
129
+ var that = this
130
+ return list.then(function(list){
131
+ return that.__unpack(list) }) }
132
+ // do the work...
133
+ return Promise.all(list)
134
+ .then(function(list){
135
+ return list.flat() }) },
136
+
68
137
 
69
138
  // iterator methods...
70
139
  //
@@ -99,21 +168,31 @@ object.Constructor('IterablePromise', Promise, {
99
168
  map: function(func){
100
169
  return this.constructor(this,
101
170
  function(e){
102
- return [func(e)] }) },
171
+ var res = func(e)
172
+ return res instanceof Promise ?
173
+ res.then(function(e){
174
+ return [e] })
175
+ : [res] }) },
103
176
  filter: function(func){
104
177
  return this.constructor(this,
105
178
  function(e){
106
- return func(e) ?
107
- [e]
108
- : [] }) },
179
+ var res = func(e)
180
+ var _filter = function(elem){
181
+ return res ?
182
+ [elem]
183
+ : [] }
184
+ return res instanceof Promise ?
185
+ res.then(_filter)
186
+ : _filter(e) }) },
109
187
  // NOTE: this does not return an iterable promise as we can't know
110
188
  // what the user reduces to...
111
189
  // XXX we could look at the initial state though...
112
190
  // NOTE: the items can be handled out of order because the nested
113
191
  // promises can resolve in any order.
114
- // XXX write how to go around this...
192
+ // XXX doc how to go around this...
115
193
  // NOTE: since order of execution can not be guaranteed there is no
116
194
  // point in implementing .reduceRight(..)
195
+ // XXX should func be able to return a promise???
117
196
  reduce: function(func, res){
118
197
  return this.constructor(this,
119
198
  function(e){
@@ -160,32 +239,25 @@ object.Constructor('IterablePromise', Promise, {
160
239
  .reverse(),
161
240
  'raw') },
162
241
 
163
- // NOTE: these can create an unresolved promise from a resolved
164
- // promise...
165
- // XXX EXPEREMENTAL...
166
- // ....can we remove a level of indirection here???
167
- // would be better to use the raw mode...
242
+ // NOTE: the following methods can create an unresolved promise from
243
+ // a resolved promise...
168
244
  concat: function(other){
169
- var lst = this.__list
170
- return lst instanceof Promise ?
171
- this.constructor([this, other])
172
- .flat()
173
- : other instanceof IterablePromise ?
174
- this.constructor(
175
- lst.concat(other.__list),
176
- 'raw')
245
+ var that = this
246
+ var cur = this.__pack(this)
247
+ var other = this.__pack(other)
248
+ return this.constructor(
249
+ // NOTE: we need to keep things as exposed as possible, this
250
+ // is why we're not blanketing all the cases with
251
+ // Promise.all(..)...
252
+ (cur instanceof Promise
253
+ && other instanceof Promise) ?
254
+ [cur, other]
255
+ : cur instanceof Promise ?
256
+ [cur, ...other]
177
257
  : other instanceof Promise ?
178
- this.constructor(
179
- lst.concat(other
180
- .then(function(res){
181
- return res instanceof Array ?
182
- res
183
- : [res] })),
184
- 'raw')
185
- : this.constructor(
186
- // XXX this is cheating -- need a more direct way to form the array...
187
- lst.concat(this.constructor(other).__list),
188
- 'raw') },
258
+ [...cur, other]
259
+ : cur.concat(other),
260
+ 'raw') },
189
261
  push: function(elem){
190
262
  return this.concat([elem]) },
191
263
  unshift: function(elem){
@@ -196,6 +268,7 @@ object.Constructor('IterablePromise', Promise, {
196
268
  // .pop()
197
269
  // .shift()
198
270
  // .first() / .last()
271
+ // .at(..)
199
272
  // ...would be nice if these could stop everything that's not
200
273
  // needed to execute...
201
274
 
@@ -268,6 +341,26 @@ object.Constructor('IterablePromise', Promise, {
268
341
  // manually handle the stop...
269
342
  // - another issue here is that the stop would happen in order of
270
343
  // execution and not order of elements...
344
+ // XXX DOC:
345
+ // inputs:
346
+ // - Chaining -- list instanceof IterablePromise
347
+ // After all the promises resolve .flat() should
348
+ // turn this into the input list.
349
+ // For this to work we'll need to at least wrap all
350
+ // arrays and promise results in arrays.
351
+ // (currently each value is wrapped)
352
+ // -> __list
353
+ // - promise (value | array)
354
+ // - array of:
355
+ // - array
356
+ // - value
357
+ // - promise (value | array)
358
+ // - New
359
+ // - promise (value | array)
360
+ // - value (non-array)
361
+ // - array of:
362
+ // - value
363
+ // - promise (value)
271
364
  __new__: function(_, list, handler){
272
365
  // instance...
273
366
  var promise
@@ -284,47 +377,10 @@ object.Constructor('IterablePromise', Promise, {
284
377
  IterablePromise)
285
378
 
286
379
  if(promise){
287
-
288
380
  if(handler != 'raw'){
289
- handler = handler
290
- ?? function(e){
291
- return [e] }
292
-
293
- // NOTE: this is recursive to handle expanding nested promises...
294
- var handle = function(elem){
295
- // call the handler...
296
- return (elem && elem.then) ?
297
- //elem.then(function(elem){
298
- // return handler(elem) })
299
- elem.then(handler)
300
- : handler(elem) }
301
-
302
- // handle the list...
303
- // NOTE: we can't .flat() the results here as we need to
304
- // wait till all the promises resolve...
305
- list =
306
- (list instanceof IterablePromise
307
- && !(list.__list instanceof Promise)) ?
308
- // NOTE: this is essentially the same as below but
309
- // with a normalized list as input...
310
- // XXX can we merge the two???
311
- list.__list
312
- .map(function(elems){
313
- return elems instanceof Promise ?
314
- elems.then(function(elems){
315
- return elems
316
- .map(handle)
317
- .flat() })
318
- : elems
319
- .map(handle)
320
- .flat() })
321
- : list instanceof Promise ?
322
- // special case: promised list...
323
- list.then(function(list){
324
- return [list].flat()
325
- .map(handle) })
326
- : [list].flat()
327
- .map(handle) }
381
+ list = list instanceof IterablePromise ?
382
+ this.__handle(list.__list, handler)
383
+ : this.__pack(list, handler) }
328
384
 
329
385
  Object.defineProperty(obj, '__list', {
330
386
  value: list,
@@ -332,14 +388,9 @@ object.Constructor('IterablePromise', Promise, {
332
388
  })
333
389
 
334
390
  // handle promise state...
335
- ;(list instanceof Promise ?
336
- // special case: promised list...
337
- list
338
- : Promise.all([list].flat()))
339
- .then(function(res){
340
- promise.resolve(handler ?
341
- res.flat()
342
- : res) })
391
+ this.__unpack(list)
392
+ .then(function(list){
393
+ promise.resolve(list) })
343
394
  .catch(promise.reject) }
344
395
 
345
396
  return obj },
@@ -547,8 +598,8 @@ object.Mixin('PromiseProtoMixin', 'soft', {
547
598
  as: ProxyPromise,
548
599
 
549
600
  // XXX
550
- iter: function(){
551
- return IterablePromise(this) },
601
+ iter: function(handler){
602
+ return IterablePromise(this, handler) },
552
603
  })
553
604
 
554
605
  PromiseProtoMixin(Promise.prototype)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ig-types",
3
- "version": "6.12.1",
3
+ "version": "6.13.6",
4
4
  "description": "Generic JavaScript types and type extensions...",
5
5
  "main": "main.js",
6
6
  "scripts": {
package/test.js CHANGED
@@ -111,45 +111,160 @@ var cases = test.Cases({
111
111
  RegExp: function(assert){
112
112
  },
113
113
 
114
- Promise: function(assert){
114
+ IterablePromise: test.TestSet(function(){
115
+ var create = function(assert, value){
116
+ return {
117
+ input: value,
118
+ output: assert(Promise.iter(value), 'Promise.iter(', value, ')'),
119
+ } }
120
+
121
+ this.Setup({
122
+ empty: function(assert){
123
+ return create(assert, []) },
124
+ value: function(assert){
125
+ return create(assert, 123) },
126
+ array: function(assert){
127
+ return create(assert, [1, 2, 3]) },
128
+ nested_array: function(assert){
129
+ return create(assert, [1, 2, [3]]) },
130
+ promise_value: function(assert){
131
+ return create(assert, Promise.resolve(123)) },
132
+ promise_array: function(assert){
133
+ return create(assert, Promise.resolve([1, 2, 3])) },
134
+ promise_nested_array: function(assert){
135
+ return create(assert, Promise.resolve([1, 2, [3]])) },
136
+ array_mixed: function(assert){
137
+ return create(assert, [1, Promise.resolve(2), 3]) },
138
+ nested_array_mixed: function(assert){
139
+ return create(assert, [
140
+ 1,
141
+ Promise.resolve(2),
142
+ [3],
143
+ Promise.resolve([4]),
144
+ ]) },
145
+ promise_array_mixed: function(assert){
146
+ return create(assert, Promise.resolve([1, Promise.resolve(2), 3])) },
147
+ 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
+ ])) },
154
+ })
155
+ this.Modifier({
156
+ nest: function(assert, setup){
157
+ setup.output = Promise.iter(setup.output)
158
+ return setup },
159
+ iter: function(assert, setup){
160
+ setup.output = setup.output.iter()
161
+ return setup },
162
+
163
+ map_asis: function(assert, setup){
164
+ setup.output = setup.output
165
+ .map(function(e){
166
+ return e })
167
+ return setup },
168
+ map_promise: function(assert, setup){
169
+ setup.output = setup.output
170
+ .map(function(e){
171
+ return Promise.resolve(e) })
172
+ return setup },
173
+
174
+ filter_all: function(assert, setup){
175
+ setup.output = setup.output
176
+ .filter(function(e){ return true })
177
+ return setup },
178
+ // XXX either the test is worng or something is broken...
179
+ filter_none: function(assert, setup){
180
+ return {
181
+ input: [],
182
+ output: setup.output
183
+ .filter(function(e){ return false }),
184
+ } },
185
+
186
+ /* XXX need tuning...
187
+ concat_basic: function(assert, {input, output}){
188
+ return {
189
+ input: [input].flat()
190
+ .concat(['a', 'b', 'c']),
191
+ output: output
192
+ .concat(['a', 'b', 'c']),
193
+ } },
194
+ concat_nested_array: function(assert, {input, output}){
195
+ return {
196
+ input: [input].flat()
197
+ .concat(['a', ['b'], 'c']),
198
+ output: output
199
+ .concat(['a', ['b'], 'c']),
200
+ } },
201
+ //*/
202
+
203
+ })
204
+ this.Test({
205
+ value: async function(assert, {input, output}){
206
+
207
+ var res = await output
208
+
209
+ assert(res instanceof Array, 'result is array')
210
+
211
+ input instanceof Array ?
212
+ // XXX this does not catch some errors -- map_promise specifically...
213
+ assert.array(res,
214
+ await Promise.all(input),
215
+ 'array -> array')
216
+ : (input instanceof Promise && await input instanceof Array) ?
217
+ assert.array(res,
218
+ await input,
219
+ 'promise array -> array')
220
+ : input instanceof Promise ?
221
+ assert.array(res,
222
+ [await input],
223
+ 'promise value -> array')
224
+ : assert.array(res,
225
+ [input],
226
+ 'value -> array') },
227
+ })
228
+ }),
229
+ Promise: async function(assert){
115
230
  var p = assert(Promise.cooperative(), '.cooperative()')
116
- //var p = assert(promise._CooperativePromise())
117
231
 
118
- assert(!p.isSet, '.isSet is false')
119
-
232
+ assert(!p.isSet, 'promise unset')
233
+
120
234
  var RESOLVE = 123
235
+ var then = false
236
+ var done = false
121
237
 
122
- var then
123
238
  p.then(function(v){
124
- // XXX this does not get printed for some reason...
125
- console.log('!!!!!!!!!!! then')
126
- // XXX this seems not to work/print/count a fail...
127
- assert(false, 'test fail')
128
-
129
- then = v })
239
+ then = assert(v == RESOLVE, '.then(..) handled') })
130
240
 
131
- assert(!p.isSet, '.isSet is false')
132
-
133
- var fin
134
241
  p.finally(function(){
135
- fin = true })
242
+ done = assert(true, '.finally(..) handled') })
136
243
 
137
- assert(!p.isSet, '.isSet is false')
244
+ assert(!p.isSet, 'promise unset')
138
245
 
139
246
  p.set(RESOLVE)
140
247
 
141
- assert(p.isSet, '.isSet')
142
-
143
- // XXX without setTimeout(..) these are run before the
144
- // .then(..) / .finally(..) have a chance to run...
145
- // ...not yet sure how I feel about this...
146
- // XXX with setTimeout(..) these appear not to have ANY effect,
147
- // as if setTimeout(..) did not run...
148
- setTimeout(function(){
149
- assert(false, 'test fail')
150
- assert(then == RESOLVE, '.then(..)')
151
- assert(fin, '.finally(..)')
152
- }, 0)
248
+ assert(p.isSet, 'promise set')
249
+
250
+ // allow the promise to finalize...
251
+ await p
252
+
253
+ assert(then, '.then(..): confirmed')
254
+ assert(done, '.done(..): confirmed')
255
+
256
+ // XXX
257
+
258
+ assert(await Promise.iter([1, Promise.resolve(2), [3]]), '.iter(..)')
259
+
260
+ assert.array(
261
+ await Promise.iter([1, 2, 3]),
262
+ [1, 2, 3],
263
+ 'basic array')
264
+ assert.array(
265
+ await Promise.iter([1, Promise.resolve(2), 3]),
266
+ [1, 2, 3],
267
+ 'promises as elements')
153
268
  },
154
269
 
155
270
  // Date.js