ig-types 6.15.1 → 6.16.1

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.
package/Array.js CHANGED
@@ -12,6 +12,7 @@
12
12
  /*********************************************************************/
13
13
 
14
14
  var object = require('ig-object')
15
+ var stoppable = require('ig-stoppable')
15
16
 
16
17
  var generator = require('./generator')
17
18
 
@@ -22,8 +23,7 @@ var generator = require('./generator')
22
23
  // NOTE: this is used in a similar fashion to Python's StopIteration...
23
24
  var STOP =
24
25
  module.STOP =
25
- object.STOP
26
-
26
+ stoppable.STOP
27
27
 
28
28
 
29
29
  //---------------------------------------------------------------------
@@ -212,8 +212,12 @@ object.Mixin('ArrayMixin', 'soft', {
212
212
  // done...
213
213
  : [] },
214
214
 
215
- iter: function*(lst=[]){
216
- yield* lst.iter() },
215
+ // XXX not sure about the handler API here yet...
216
+ iter: function*(lst=[], handler=undefined){
217
+ yield* lst.iter(
218
+ ...(handler ?
219
+ [handler]
220
+ : [])) },
217
221
  })
218
222
 
219
223
 
@@ -488,8 +492,22 @@ object.Mixin('ArrayProtoMixin', 'soft', {
488
492
  // -> iterator
489
493
  //
490
494
  // XXX should this take an argument and be like map??
491
- iter: function*(){
492
- yield* this },
495
+ // XXX this should handle throwing STOP!!!
496
+ // ...might also ne a good idea to isolate the STOP mechanics
497
+ // into a spearate module/package...
498
+ iter: stoppable(function*(handler=undefined){
499
+ if(handler){
500
+ var i = 0
501
+ for(var e of this){
502
+ var res = handler.call(this, e, i++)
503
+ // treat non-iterables as single elements...
504
+ if(typeof(res) == 'object'
505
+ && Symbol.iterator in res){
506
+ yield* res
507
+ } else {
508
+ yield res } }
509
+ } else {
510
+ yield* this }}),
493
511
 
494
512
 
495
513
  // Stoppable iteration...
package/Function.js ADDED
@@ -0,0 +1,18 @@
1
+ /**********************************************************************
2
+ *
3
+ *
4
+ *
5
+ **********************************************/ /* c8 ignore next 2 */
6
+ ((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define)
7
+ (function(require){ var module={} // make module AMD/node compatible...
8
+ /*********************************************************************/
9
+
10
+
11
+ var AsyncFunction =
12
+ module.AsyncFunction =
13
+ (async function(){}).constructor
14
+
15
+
16
+
17
+ /**********************************************************************
18
+ * vim:set ts=4 sw=4 : */ return module })
package/Promise.js CHANGED
@@ -30,6 +30,8 @@
30
30
 
31
31
  var object = require('ig-object')
32
32
 
33
+ //var generator = require('./generator')
34
+
33
35
 
34
36
 
35
37
  //---------------------------------------------------------------------
@@ -58,6 +60,7 @@ var object = require('ig-object')
58
60
  //
59
61
  // XXX how do we handle errors/rejections???
60
62
  // ...mostly the current state is OK, but need more testing...
63
+ // XXX add support for async generators...
61
64
  //
62
65
 
63
66
  var iterPromiseProxy =
@@ -117,6 +120,11 @@ object.Constructor('IterablePromise', Promise, {
117
120
  // stop will stop the handlers not yet run and not the next
118
121
  // handlers in sequence.
119
122
  // XXX EXPEREMENTAL: STOP...
123
+ // XXX add support for async generators...
124
+ // ...an async generator is not "parallel", i.e. intil one
125
+ // returned promise is resolved the generator blocks (will not
126
+ // advance)...
127
+ // ...can we feed out a results one by one???
120
128
  __pack: function(list, handler=undefined){
121
129
  var that = this
122
130
  // handle iterable promise list...
@@ -198,20 +206,6 @@ object.Constructor('IterablePromise', Promise, {
198
206
  : handler(elem) }) },
199
207
  //*/
200
208
  // transform/handle packed array (sync)...
201
- //
202
- // XXX BUG:
203
- // await Promise.iter(['a', Promise.resolve(222), ['c']])
204
- // .map(async e => e)
205
- // -> ['a', <promise>, ['c']]
206
- // is not the same as:
207
- // await Promise.iter(['a', Promise.resolve(222), ['c']])
208
- // .map(e => e)
209
- // -> ['a', 222, ['c']]
210
- // ...and these works as expected:
211
- // await Promise.iter(['a', Promise.resolve(222), ['c']], async e => [e])
212
- // -> ['a', 222, ['c']]
213
- // await Promise.iter(['a', Promise.resolve(222), ['c']], e => [e])
214
- // -> ['a', 222, ['c']]
215
209
  __handle: function(list, handler=undefined){
216
210
  var that = this
217
211
  if(typeof(list) == 'function'){
@@ -300,6 +294,8 @@ object.Constructor('IterablePromise', Promise, {
300
294
  .then(function(){
301
295
  return res }) },
302
296
 
297
+ // XXX .chain(..) -- see generator.chain(..)
298
+
303
299
  flat: function(depth=1){
304
300
  return this.constructor(this,
305
301
  function(e){
@@ -468,6 +464,11 @@ object.Constructor('IterablePromise', Promise, {
468
464
  every: promiseProxy('every'),
469
465
 
470
466
 
467
+ join: async function(){
468
+ return [...(await this)]
469
+ .join(...arguments) },
470
+
471
+
471
472
  // this is defined globally as Promise.prototype.iter(..)
472
473
  //
473
474
  // for details see: PromiseMixin(..) below...
package/README.md CHANGED
@@ -13,6 +13,8 @@ Library of JavaScript type extensions, types and utilities.
13
13
  - [`Object.matchPartial(..)`](#objectmatchpartial)
14
14
  - [`<object>.run(..)`](#objectrun)
15
15
  - [`Object.sort(..)`](#objectsort)
16
+ - [`Function`](#function)
17
+ - [`func.AsyncFunction`](#funcasyncfunction)
16
18
  - [`Array`](#array)
17
19
  - [`<array>.first(..)` / `<array>.last(..)`](#arrayfirst--arraylast)
18
20
  - [`<array>.rol(..)`](#arrayrol)
@@ -78,6 +80,7 @@ Library of JavaScript type extensions, types and utilities.
78
80
  - [`<promise-iter>.concat(..)`](#promise-iterconcat)
79
81
  - [`<promise-iter>.push(..)` / `<promise-iter>.unshift(..)`](#promise-iterpush--promise-iterunshift)
80
82
  - [`<promise-iter>.at(..)` / `<promise-iter>.first()` / `<promise-iter>.last()`](#promise-iterat--promise-iterfirst--promise-iterlast)
83
+ - [`<promise-iter>.join(..)`](#promise-iterjoin)
81
84
  - [`<promise-iter>.some(..)` / `<promise-iter>.find(..)`](#promise-itersome--promise-iterfind)
82
85
  - [Array proxy methods returning `<promise-iter>`](#array-proxy-methods-returning-promise-iter)
83
86
  - [Array proxy methods returning a `<promise>`](#array-proxy-methods-returning-a-promise)
@@ -94,7 +97,7 @@ Library of JavaScript type extensions, types and utilities.
94
97
  - [`generator.iter(..)`](#generatoriter)
95
98
  - [`generator.STOP`](#generatorstop)
96
99
  - [Generator instance iteration](#generator-instance-iteration)
97
- - [`<generator>.iter()`](#generatoriter-1)
100
+ - [`<generator>.iter(..)`](#generatoriter-1)
98
101
  - [`<generator>.map(..)` / `<generator>.filter(..)`](#generatormap--generatorfilter)
99
102
  - [`<generator>.reduce(..)` / `<generator>.greduce(..)`](#generatorreduce--generatorgreduce)
100
103
  - [`<generator>.slice(..)`](#generatorslice)
@@ -102,7 +105,7 @@ Library of JavaScript type extensions, types and utilities.
102
105
  - [`<generator>.flat(..)`](#generatorflat)
103
106
  - [`<generator>.shift()` / `<generator>.pop()` / `<generator>.gshift()` / `<generator>.gpop()`](#generatorshift--generatorpop--generatorgshift--generatorgpop)
104
107
  - [`<generator>.unshift(..)` / `<generator>.push(..)`](#generatorunshift--generatorpush)
105
- - [`<generator>.promise()`](#generatorpromise)
108
+ - [`<generator>.join(..)`](#generatorjoin)
106
109
  - [`<generator>.then(..)` / `<generator>.catch(..)` / `<generator>.finally(..)`](#generatorthen--generatorcatch--generatorfinally)
107
110
  - [`<generator>.toArray()`](#generatortoarray)
108
111
  - [Treating iterators the same as generators](#treating-iterators-the-same-as-generators)
@@ -114,6 +117,7 @@ Library of JavaScript type extensions, types and utilities.
114
117
  - [`<Generator>.slice(..)`](#generatorslice-1)
115
118
  - [`<Generator>.map(..)` / `<Generator>.filter(..)` / `<Generator>.reduce(..)` / `<Generator>.flat()`](#generatormap--generatorfilter--generatorreduce--generatorflat)
116
119
  - [`<Generator>.toArray()`](#generatortoarray-1)
120
+ - [`<Generator>.join(..)`](#generatorjoin-1)
117
121
  - [`<Generator>.then(..)` / `<Generator>.catch(..)` / `<Generator>.finally(..)`](#generatorthen--generatorcatch--generatorfinally-1)
118
122
  - [Generator combinators](#generator-combinators)
119
123
  - [`<Generator>.chain(..)` / `<generator>.chain(..)`](#generatorchain--generatorchain)
@@ -124,6 +128,15 @@ Library of JavaScript type extensions, types and utilities.
124
128
  - [`generator.produce(..)`](#generatorproduce)
125
129
  - [Generator helpers](#generator-helpers)
126
130
  - [`generator.stoppable(..)`](#generatorstoppable)
131
+ - [Async generator extensions](#async-generator-extensions)
132
+ - [`generator.AsyncGenerator`](#generatorasyncgenerator)
133
+ - [`<async-generator>.then(..)` / `<async-generator>.catch(..)` / `<async-generator>.finally(..)`](#async-generatorthen--async-generatorcatch--async-generatorfinally)
134
+ - [`<async-generator>.iter(..)`](#async-generatoriter)
135
+ - [`<async-generator>.map(..)` / `<async-generator>.filter(..)` / `<async-generator>.reduce(..)`](#async-generatormap--async-generatorfilter--async-generatorreduce)
136
+ - [`<async-generator>.chain(..)`](#async-generatorchain)
137
+ - [`<async-generator>.flat(..)`](#async-generatorflat)
138
+ - [`<async-generator>.concat(..)`](#async-generatorconcat)
139
+ - [`<async-generator>.push(..)` / `<async-generator>.unshift(..)`](#async-generatorpush--async-generatorunshift)
127
140
  - [Containers](#containers)
128
141
  - [`containers.UniqueKeyMap()` (`Map`)](#containersuniquekeymap-map)
129
142
  - [`<unique-key-map>.set(..)`](#unique-key-mapset)
@@ -446,6 +459,30 @@ Object.keys(Object.sort(o, ['x', 'a', '100']))
446
459
  This is similar to [`<map>.sort(..)`](#mapsort) and [`<ser>.sort(..)`](#setsort).
447
460
 
448
461
 
462
+ ## `Function`
463
+
464
+ ```javascript
465
+ var func = require('ig-types/Function')
466
+ ```
467
+
468
+ ### `func.AsyncFunction`
469
+
470
+ The async function constructor.
471
+
472
+ This enables us to test if an object is an instance of an async function.
473
+
474
+ ```javascript
475
+ var a = async function(){
476
+ // ...
477
+ }
478
+
479
+ a instanceof func.AsyncFunction // -> true
480
+ ```
481
+
482
+ This is hidden by JavaScript by default.
483
+
484
+
485
+
449
486
  ## `Array`
450
487
 
451
488
  ```javascript
@@ -1677,6 +1714,12 @@ parent `<promise-iter>`.
1677
1714
 
1678
1715
  XXX
1679
1716
 
1717
+
1718
+ #### `<promise-iter>.join(..)`
1719
+
1720
+ XXX
1721
+
1722
+
1680
1723
  #### `<promise-iter>.some(..)` / `<promise-iter>.find(..)`
1681
1724
 
1682
1725
  ```bnf
@@ -2023,7 +2066,7 @@ Chained generators handle items depth-first, i.e. the items are passed as they
2023
2066
  are yielded down the generator chain.
2024
2067
 
2025
2068
 
2026
- #### `<generator>.iter()`
2069
+ #### `<generator>.iter(..)`
2027
2070
 
2028
2071
  Iterate over the generator.
2029
2072
  ```bnf
@@ -2031,7 +2074,24 @@ Iterate over the generator.
2031
2074
  -> <generator>
2032
2075
  ```
2033
2076
 
2034
- This is here mainly for compatibility with [`<array>`'s `.iter()`](#arrayiter--arrayiter).
2077
+ XXX move this to `generator.iter(..)`
2078
+
2079
+ Compatible with [`<array>`'s `.iter()`](#arrayiter--arrayiter).
2080
+
2081
+ `.iter(..)` also supports a handler function
2082
+ ```bnf
2083
+ <generator>.iter(<handler>)
2084
+ -> <generator>
2085
+
2086
+
2087
+ <handler>(<elem>, <index>)
2088
+ -> <elem>
2089
+ -> [<elem>, ..]
2090
+ -> []
2091
+ ```
2092
+
2093
+ Note that the iterables returned by `<handler>(..)` will be expanded, to prevent
2094
+ this wrap them in an array.
2035
2095
 
2036
2096
 
2037
2097
  #### `<generator>.map(..)` / `<generator>.filter(..)`
@@ -2156,30 +2216,34 @@ Value added by `.unshift(..)` will be yielded by `<generator>` "first", i.e. on
2156
2216
  _next_ call to `.next()`, regardless of the current generator state.
2157
2217
 
2158
2218
 
2159
- #### `<generator>.promise()`
2219
+ #### `<generator>.join(..)`
2220
+
2221
+ XXX
2222
+
2223
+
2224
+ #### `<generator>.then(..)` / `<generator>.catch(..)` / `<generator>.finally(..)`
2225
+
2226
+ Return a promise and resolve it with the generator value.
2160
2227
 
2161
2228
  ```bnf
2162
- <generator>.promise()
2229
+ <generator>.then()
2163
2230
  -> <promise>
2164
2231
  ```
2165
- Return a promise and resolve it with the generator value.
2166
-
2167
- Note that this will deplete the generator.
2168
2232
 
2169
-
2170
- #### `<generator>.then(..)` / `<generator>.catch(..)` / `<generator>.finally(..)`
2233
+ Adding handlers to the promise
2171
2234
 
2172
2235
  ```bnf
2173
2236
  <generator>.then(<resolve>, <reject>)
2174
2237
  -> <promise>
2175
2238
 
2176
- <generator>.then(<reject>)
2239
+ <generator>.then(<resolve>)
2177
2240
  -> <promise>
2178
2241
 
2179
2242
  <generator>.finally(<handler>)
2180
2243
  -> <promise>
2181
2244
  ```
2182
- Shorthands to `<generator>.promise().then(..)` / `<generator>.promise().catch(..)` / `<generator>.promise().finally(..)`
2245
+
2246
+ Note that this will deplete the generator.
2183
2247
 
2184
2248
  These are the same as equivalent `Promise` methods, for more info see:
2185
2249
  https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
@@ -2360,6 +2424,10 @@ Return a function that will return a `<generator>` output as an `Array`.
2360
2424
  -> <function>
2361
2425
  ```
2362
2426
 
2427
+ #### `<Generator>.join(..)`
2428
+
2429
+ XXX
2430
+
2363
2431
 
2364
2432
  #### `<Generator>.then(..)` / `<Generator>.catch(..)` / `<Generator>.finally(..)`
2365
2433
 
@@ -2483,6 +2551,26 @@ stoppable(<generator>)
2483
2551
 
2484
2552
  <!-- XXX example? -->
2485
2553
 
2554
+ ## Async generator extensions
2555
+
2556
+ XXX EXPERIMENTAL
2557
+
2558
+ #### `generator.AsyncGenerator`
2559
+
2560
+ #### `<async-generator>.then(..)` / `<async-generator>.catch(..)` / `<async-generator>.finally(..)`
2561
+
2562
+ #### `<async-generator>.iter(..)`
2563
+
2564
+ #### `<async-generator>.map(..)` / `<async-generator>.filter(..)` / `<async-generator>.reduce(..)`
2565
+
2566
+ #### `<async-generator>.chain(..)`
2567
+
2568
+ #### `<async-generator>.flat(..)`
2569
+
2570
+ #### `<async-generator>.concat(..)`
2571
+
2572
+ #### `<async-generator>.push(..)` / `<async-generator>.unshift(..)`
2573
+
2486
2574
 
2487
2575
 
2488
2576
  ## Containers
package/event.js CHANGED
@@ -120,6 +120,8 @@ object.Constructor('Eventful', {
120
120
  Object.defineProperty(context, '__event_handlers__', {
121
121
  value: {[this.name]: (handlers = [])},
122
122
  enumerable: false,
123
+ configurable: true,
124
+ writable: true,
123
125
  })
124
126
  && handlers
125
127
  : (context.__event_handlers__[this.name] =
@@ -293,6 +295,8 @@ module.EventHandlerMixin = object.Mixin('EventHandlerMixin', {
293
295
  && Object.defineProperty(this, '__event_handlers__', {
294
296
  value: {},
295
297
  enumerable: false,
298
+ configurable: true,
299
+ writable: true,
296
300
  })
297
301
  ;(this.__event_handlers__[evt] =
298
302
  this.__event_handlers__[evt] || [])
@@ -343,14 +347,14 @@ module.EventDocMixin = object.Mixin('EventDocMixin', {
343
347
  return object.deepKeys(this)
344
348
  .filter(function(n){
345
349
  // avoid triggering props...
346
- return !object.values(this, n, function(){ return object.STOP }, true)[0].get
350
+ return !object.values(this, n, true).next().value.get
347
351
  // XXX this is too strict...
348
352
  && (this[n] || {}).constructor === Eventful}.bind(this)) },
349
353
  get events(){
350
354
  return object.deepKeys(this)
351
355
  .filter(function(n){
352
356
  // avoid triggering props...
353
- return !object.values(this, n, function(){ return object.STOP }, true)[0].get
357
+ return !object.values(this, n, true).next().value.get
354
358
  // XXX this is too strict...
355
359
  && (this[n] || {}).constructor === Event }.bind(this)) },
356
360
  })
package/generator.js CHANGED
@@ -8,6 +8,7 @@
8
8
  /*********************************************************************/
9
9
 
10
10
  var object = require('ig-object')
11
+ var stoppable = require('ig-stoppable')
11
12
 
12
13
 
13
14
 
@@ -16,7 +17,7 @@ var object = require('ig-object')
16
17
  // NOTE: this is used in a similar fashion to Python's StopIteration...
17
18
  var STOP =
18
19
  module.STOP =
19
- object.STOP
20
+ stoppable.STOP
20
21
 
21
22
 
22
23
  //---------------------------------------------------------------------
@@ -38,11 +39,11 @@ module.STOP =
38
39
  // of each of them.
39
40
  // So, below we will define:
40
41
  //
41
- // GeneratorPrototype
42
+ // Generator.prototype
42
43
  // prototype of the generator constructors (i.e. Iter(..) from the
43
44
  // above example)
44
45
  //
45
- // GeneratorPrototype.prototype
46
+ // Generator.prototype.prototype
46
47
  // generator instance prototype (i.e. iter for the above code)
47
48
  //
48
49
  //
@@ -58,17 +59,10 @@ module.STOP =
58
59
  //
59
60
  //---------------------------------------------------------------------
60
61
 
61
- var GeneratorPrototype =
62
- (function*(){}).constructor.prototype
63
-
64
62
  var Generator =
65
63
  module.Generator =
66
64
  (function*(){}).constructor
67
65
 
68
-
69
- var AsyncGeneratorPrototype =
70
- (async function*(){}).constructor.prototype
71
-
72
66
  var AsyncGenerator =
73
67
  module.AsyncGenerator =
74
68
  (async function*(){}).constructor
@@ -85,19 +79,44 @@ var ITERATOR_PROTOTYPES = [
85
79
 
86
80
 
87
81
  //---------------------------------------------------------------------
88
-
89
82
  // generic generator wrapper...
83
+
84
+ // helper...
85
+ var __iter =
86
+ module.__iter =
87
+ function*(lst=[]){
88
+ if(typeof(lst) == 'object'
89
+ && Symbol.iterator in lst){
90
+ yield* lst
91
+ } else {
92
+ yield lst } }
93
+
94
+ // XXX updatae Array.js' version for compatibility...
95
+ // XXX DOCS!!!
90
96
  var iter =
91
97
  module.iter =
92
98
  Generator.iter =
93
- function*(lst=[]){
94
- for(var e of lst){
95
- yield e } }
99
+ stoppable(function(lst=[]){
100
+ // handler -> generator-constructor...
101
+ if(typeof(lst) == 'function'){
102
+ // we need to be callable...
103
+ var that = this instanceof Function ?
104
+ this
105
+ // generic root generator...
106
+ : module.__iter
107
+ return function*(){
108
+ yield* that(...arguments).iter(lst) } }
109
+ // no handler -> generator instance...
110
+ return module.__iter(lst) })
111
+
112
+ // NOTE: we need .iter(..) to both return generators if passed an iterable
113
+ // and genereator constructos if passed a function...
114
+ iter.__proto__ = Generator.prototype
96
115
 
97
116
 
98
117
 
99
118
  //---------------------------------------------------------------------
100
- // GeneratorPrototype "class" methods...
119
+ // Generator.prototype "class" methods...
101
120
  //
102
121
  // the following are effectively the same:
103
122
  // 1) Wrapper
@@ -121,9 +140,11 @@ Generator.iter =
121
140
 
122
141
  //
123
142
  // makeGenerator(<name>)
143
+ // makeGenerator(<name>, <handler>)
124
144
  // -> <func>
125
145
  //
126
- // makeGenerator(<name>, <handler>)
146
+ // makeGenerator('async', <name>)
147
+ // makeGenerator('async', <name>, <handler>)
127
148
  // -> <func>
128
149
  //
129
150
  //
@@ -140,14 +161,26 @@ Generator.iter =
140
161
  // XXX this needs to be of the correct type... (???)
141
162
  // XXX need to accept generators as handlers...
142
163
  var makeGenerator = function(name, pre){
164
+ var sync = true
165
+ if(name == 'async'){
166
+ sync = false
167
+ var [name, pre] = [...arguments].slice(1) }
143
168
  return function(...args){
144
169
  var that = this
145
170
  return Object.assign(
146
- function*(){
147
- var a = pre ?
148
- pre.call(this, args, ...arguments)
149
- : args
150
- yield* that(...arguments)[name](...a) },
171
+ // NOTE: the two branches here are identical, the only
172
+ // difference is the async keyword...
173
+ sync ?
174
+ function*(){
175
+ var a = pre ?
176
+ pre.call(this, args, ...arguments)
177
+ : args
178
+ yield* that(...arguments)[name](...a) }
179
+ : async function*(){
180
+ var a = pre ?
181
+ pre.call(this, args, ...arguments)
182
+ : args
183
+ yield* that(...arguments)[name](...a) },
151
184
  { toString: function(){
152
185
  return [
153
186
  that.toString(),
@@ -163,34 +196,6 @@ var makePromise = function(name){
163
196
  return that(...arguments)[name](func) } } }
164
197
 
165
198
 
166
- var stoppable =
167
- module.stoppable =
168
- function(func){
169
- return Object.assign(
170
- func instanceof Generator ?
171
- function*(){
172
- try{
173
- yield* func.call(this, ...arguments)
174
- } catch(err){
175
- if(err === STOP){
176
- return
177
- } else if(err instanceof STOP){
178
- yield err.value
179
- return }
180
- throw err } }
181
- : function(){
182
- try{
183
- return func.call(this, ...arguments)
184
- } catch(err){
185
- if(err === STOP){
186
- return
187
- } else if(err instanceof STOP){
188
- return err.value }
189
- throw err } },
190
- { toString: function(){
191
- return func.toString() }, }) }
192
-
193
-
194
199
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
195
200
 
196
201
  var GeneratorMixin =
@@ -198,9 +203,7 @@ module.GeneratorMixin =
198
203
  object.Mixin('GeneratorMixin', 'soft', {
199
204
  STOP: object.STOP,
200
205
 
201
- // NOTE: this is here for compatibility with Array.iter(..)
202
- iter: function*(lst=[]){
203
- yield* module.iter(lst) },
206
+ iter: module.iter,
204
207
 
205
208
  gat: makeGenerator('gat'),
206
209
  at: function(i){
@@ -229,7 +232,7 @@ object.Mixin('GeneratorMixin', 'soft', {
229
232
  return that(...arguments).toArray() },
230
233
  { toString: function(){
231
234
  return that.toString()
232
- + '\n .toString()'}, }) },
235
+ + '\n .toArray()'}, }) },
233
236
  gpop: makeGenerator('gpop'),
234
237
  pop: function(){
235
238
  var that = this
@@ -239,7 +242,7 @@ object.Mixin('GeneratorMixin', 'soft', {
239
242
  return that(...arguments).pop() },
240
243
  { toString: function(){
241
244
  return that.toString()
242
- + '\n .gpop()'}, }) },
245
+ + '\n .pop()'}, }) },
243
246
  push: makeGenerator('push'),
244
247
  gshift: makeGenerator('gshift'),
245
248
  shift: function(){
@@ -250,7 +253,7 @@ object.Mixin('GeneratorMixin', 'soft', {
250
253
  return that(...arguments).shift() },
251
254
  { toString: function(){
252
255
  return that.toString()
253
- + '\n .gshift()'}, }) },
256
+ + '\n .shift()'}, }) },
254
257
  unshift: makeGenerator('unshift'),
255
258
 
256
259
  // promises...
@@ -272,15 +275,43 @@ object.Mixin('GeneratorMixin', 'soft', {
272
275
  e(...args)
273
276
  : e }) }),
274
277
  //zip: makeGenerator('zip'),
278
+
279
+ enumerate: makeGenerator('enumerate'),
280
+
281
+ // XXX should this have a .gjoin(..) companion...
282
+ join: function(){
283
+ var args = [...arguments]
284
+ var that = this
285
+ return Object.assign(
286
+ function(){
287
+ //return that(...arguments).toArray().shift() },
288
+ return that(...arguments).join(...args) },
289
+ { toString: function(){
290
+ return that.toString()
291
+ + '\n .join()'}, }) },
275
292
  })
276
293
 
277
294
 
278
295
  var GeneratorProtoMixin =
279
296
  module.GeneratorProtoMixin =
280
297
  object.Mixin('GeneratorProtoMixin', 'soft', {
281
- // NOTE: this is here for compatibility with [..].iter()
282
- iter: function*(){
283
- yield* this },
298
+ // XXX use module.iter(..) ???
299
+ iter: stoppable(function*(handler){
300
+ if(handler){
301
+ var i = 0
302
+ for(var elem of this){
303
+ var res = handler.call(this, elem, i)
304
+ // expand iterables...
305
+ if(typeof(res) == 'object'
306
+ && Symbol.iterator in res){
307
+ yield* res
308
+ // as-is...
309
+ } else {
310
+ yield res }}
311
+ // no handler...
312
+ } else {
313
+ yield* this } }),
314
+ //*/
284
315
 
285
316
  at: function(i){
286
317
  return this.gat(i).next().value },
@@ -390,17 +421,19 @@ object.Mixin('GeneratorProtoMixin', 'soft', {
390
421
 
391
422
  // promises...
392
423
  //
393
- // XXX how do we handle reject(..) / .catch(..)???
394
- promise: function(){
424
+ then: function(onresolve, onreject){
395
425
  var that = this
396
- return new Promise(function(resolve){
397
- resolve([...that]) }) },
398
- then: function(func){
399
- return this.promise().then(func) },
426
+ var p = new Promise(
427
+ function(resolve){
428
+ resolve([...that]) })
429
+ p = (onresolve || onreject) ?
430
+ p.then(...arguments)
431
+ : p
432
+ return p },
400
433
  catch: function(func){
401
- return this.promise().catch(func) },
434
+ return this.then().catch(func) },
402
435
  finally: function(func){
403
- return this.promise().finally(func) },
436
+ return this.then().finally(func) },
404
437
 
405
438
  // combinators...
406
439
  //
@@ -423,11 +456,20 @@ object.Mixin('GeneratorProtoMixin', 'soft', {
423
456
  // XXX
424
457
  },
425
458
  //*/
459
+
460
+ enumerate: function*(){
461
+ var i = 0
462
+ for(var e of this){
463
+ yield [i++, e] } },
464
+
465
+ join: function(){
466
+ return [...this]
467
+ .join(...arguments) },
426
468
  })
427
469
 
428
470
 
429
- GeneratorMixin(GeneratorPrototype)
430
- GeneratorProtoMixin(GeneratorPrototype.prototype)
471
+ GeneratorMixin(Generator.prototype)
472
+ GeneratorProtoMixin(Generator.prototype.prototype)
431
473
 
432
474
 
433
475
  // Extend base iterators...
@@ -439,36 +481,106 @@ ITERATOR_PROTOTYPES
439
481
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
440
482
  // XXX EXPERIMENTAL...
441
483
 
442
- var makeAsyncGenerator = function(name, pre){
443
- return function(...args){
444
- var that = this
445
- return Object.assign(
446
- async function*(){
447
- var a = pre ?
448
- pre.call(this, args, ...arguments)
449
- : args
450
- for await (var e of that(...arguments)[name](...a)){
451
- yield e } },
452
- { toString: function(){
453
- return [
454
- that.toString(),
455
- // XXX need to normalize args better...
456
- `.${ name }(${ args.join(', ') })`,
457
- ].join('\n ') }, }) } }
458
-
459
484
  var AsyncGeneratorMixin =
460
485
  module.AsyncGeneratorMixin =
461
486
  object.Mixin('AsyncGeneratorMixin', 'soft', {
462
- map: makeAsyncGenerator('map'),
487
+ // XXX TEST...
488
+ iter: makeGenerator('async', 'iter'),
489
+
490
+ map: makeGenerator('async', 'map'),
491
+ filter: makeGenerator('async', 'filter'),
492
+ reduce: makeGenerator('async', 'reduce'),
463
493
  })
464
494
 
465
495
  var AsyncGeneratorProtoMixin =
466
496
  module.AsyncGeneratorProtoMixin =
467
497
  object.Mixin('AsyncGeneratorProtoMixin', 'soft', {
498
+ // promise...
499
+ //
500
+ // NOTE: this will unwind the generator...
501
+ // XXX create an iterator promise???
502
+ // XXX should we unwind???
503
+ then: function(resolve, reject){
504
+ var that = this
505
+ var p = new Promise(async function(_resolve, _reject){
506
+ var res = []
507
+ for await(var elem of that){
508
+ res.push(elem) }
509
+ _resolve(res) })
510
+ p = (resolve || reject) ?
511
+ p.then(...arguments)
512
+ : p
513
+ return p },
514
+ catch: function(func){
515
+ return this.then().catch(func) },
516
+ finally: function(){
517
+ return this.then().finally(func) },
518
+
519
+ // XXX might be a good idea to use this approach above...
520
+ iter: stoppable(async function*(handler=undefined){
521
+ var i = 0
522
+ if(handler){
523
+ for await(var e of this){
524
+ var res = handler.call(this, e, i++)
525
+ if(typeof(res) == 'object'
526
+ && Symbol.iterator in res){
527
+ yield* res
528
+ } else {
529
+ yield res } }
530
+ } else {
531
+ yield* this } }),
532
+
533
+ map: async function*(func){
534
+ yield* this.iter(function(elem, i){
535
+ return [func.call(this, elem, i)] }) },
536
+ filter: async function*(func){
537
+ yield* this.iter(function(elem, i){
538
+ return func.call(this, elem, i) ?
539
+ [elem]
540
+ : [] }) },
541
+ // NOTE: there is not much point in .reduceRight(..) in an async
542
+ // generator as we'll need to fully unwind it then go from the
543
+ // end...
544
+ reduce: async function(func, state){
545
+ this.iter(function(elem, i){
546
+ state = func.call(this, state, elem, i)
547
+ return [] })
548
+ return state },
549
+
550
+ // XXX TEST...
551
+ chain: async function*(...next){
552
+ yield* next
553
+ .reduce(function(cur, next){
554
+ return next(cur) }, this) },
555
+
556
+ flat: async function*(){
557
+ for await(var e of this){
558
+ if(e instanceof Array){
559
+ yield* e
560
+ } else {
561
+ yield e }}},
562
+
563
+ concat: async function*(other){
564
+ yield* this
565
+ yield* other },
566
+ push: async function*(elem){
567
+ yield* this
568
+ yield elem },
569
+ unsift: async function*(elem){
570
+ yield elem
571
+ yield* this },
572
+
573
+ join: async function(){
574
+ return [...(await this)]
575
+ .join(...arguments) },
576
+
577
+ // XXX
578
+ // slice -- not sure if we need this...
579
+ // ...
468
580
  })
469
581
 
470
- //AsyncGeneratorMixin(AsyncGeneratorPrototype)
471
- //AsyncGeneratorProtoMixin(AsyncGeneratorPrototype.prototype)
582
+ AsyncGeneratorMixin(AsyncGenerator.prototype)
583
+ AsyncGeneratorProtoMixin(AsyncGenerator.prototype.prototype)
472
584
 
473
585
 
474
586
 
package/main.js CHANGED
@@ -22,6 +22,7 @@ module.patchDate = require('./Date').patchDate
22
22
 
23
23
  // Additional types...
24
24
  module.containers = require('./containers')
25
+ module.func = require('./Function')
25
26
  module.generator = require('./generator')
26
27
  module.event = require('./event')
27
28
  module.runner = require('./runner')
@@ -31,7 +32,9 @@ module.runner = require('./runner')
31
32
  module.STOP = object.STOP
32
33
 
33
34
  // frequently used stuff...
35
+ module.AsyncFunction = module.func.AsyncFunction
34
36
  module.Generator = module.generator.Generator
37
+ module.AsyncGenerator = module.generator.AsyncGenerator
35
38
  // XXX doc...
36
39
  module.iter = module.generator.iter
37
40
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ig-types",
3
- "version": "6.15.1",
3
+ "version": "6.16.1",
4
4
  "description": "Generic JavaScript types and type extensions...",
5
5
  "main": "main.js",
6
6
  "scripts": {
@@ -23,7 +23,8 @@
23
23
  },
24
24
  "homepage": "https://github.com/flynx/types.js#readme",
25
25
  "dependencies": {
26
- "ig-object": "^5.4.16",
26
+ "ig-object": "^6.0.0",
27
+ "ig-stoppable": "^2.0.0",
27
28
  "object-run": "^1.0.1"
28
29
  },
29
30
  "devDependencies": {