mirror of
https://github.com/flynx/types.js.git
synced 2025-10-29 02:20:07 +00:00
IterablePromise's .filter(..) broken...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
5d6462b9aa
commit
1e124ea752
180
Promise.js
180
Promise.js
@ -124,137 +124,6 @@ object.Constructor('IterablePromise', Promise, {
|
||||
// handlers in sequence.
|
||||
// XXX EXPEREMENTAL: STOP...
|
||||
// XXX ITER can we unwind (sync/async) generators one by one???
|
||||
/* XXX this repeats part of the functionality of .__handle(..)
|
||||
__pack: function(list, handler=undefined, onerror=undefined){
|
||||
var that = this
|
||||
// handle iterator...
|
||||
// XXX ITER do we unwind the iterator here or wait to unwind later???
|
||||
if(typeof(list) == 'object'
|
||||
&& Symbol.iterator in list){
|
||||
if(!onerror){
|
||||
list = [...list]
|
||||
// handle errors in input generator...
|
||||
// NOTE: this does not offer the most control because semantically
|
||||
// we bust behave in the same manner as <generator>.iter(..)
|
||||
} else {
|
||||
var res = []
|
||||
try{
|
||||
for(var e of list){
|
||||
res.push(e) }
|
||||
}catch(err){
|
||||
var r = onerror(err)
|
||||
r !== undefined
|
||||
&& res.push(r) }
|
||||
list = res } }
|
||||
// handle iterable promise...
|
||||
if(list instanceof IterablePromise){
|
||||
return this.__handle(list.__packed, handler, onerror) }
|
||||
// handle promise / async-iterator...
|
||||
// XXX ITER do we unwind the iterator here or wait to unwind later???
|
||||
if(typeof(list) == 'object'
|
||||
&& Symbol.asyncIterator in list){
|
||||
return list
|
||||
.iter(handler, onerror)
|
||||
.then(function(list){
|
||||
return that.__pack(list) }) }
|
||||
if(list instanceof Promise){
|
||||
return list
|
||||
.then(function(list){
|
||||
return that.__pack(list, handler, onerror) }) }
|
||||
// do the work...
|
||||
// NOTE: packing and handling are mixed here because it's faster
|
||||
// to do them both on a single list traverse...
|
||||
var handle = !!handler
|
||||
handler = handler
|
||||
?? function(elem){
|
||||
return [elem] }
|
||||
// XXX this repeats .__handle(..), need to unify...
|
||||
var stop = false
|
||||
var map = 'map'
|
||||
var pack = function(){
|
||||
return [list].flat()
|
||||
[map](function(elem){
|
||||
// XXX EXPEREMENTAL...
|
||||
return elem instanceof IterablePromise ?
|
||||
(elem.isSync() ?
|
||||
handler(elem.sync())
|
||||
// XXX need to handle this but keep it IterablePromise...
|
||||
: elem.iterthen(handler))
|
||||
: (elem instanceof SyncPromise
|
||||
&& !(elem.sync() instanceof Promise)) ?
|
||||
handler(elem.sync())
|
||||
: elem && elem.then ?
|
||||
(handleSTOP ?
|
||||
// stoppable -- need to handle stop async...
|
||||
elem
|
||||
.then(function(res){
|
||||
return !stop ?
|
||||
handler(res)
|
||||
: [] })
|
||||
// NOTE: we are using .catch(..) here
|
||||
// instead of directly passing the
|
||||
// error handler to be able to catch
|
||||
// the STOP from the handler...
|
||||
.catch(handleSTOP)
|
||||
// non-stoppable...
|
||||
: elem.then(handler))
|
||||
: elem instanceof Array ?
|
||||
handler(elem)
|
||||
// NOTE: we keep things that do not need protecting
|
||||
// from .flat() as-is...
|
||||
: !handle ?
|
||||
elem
|
||||
: handler(elem) }) }
|
||||
// pack (stoppable)...
|
||||
if(!!this.constructor.STOP){
|
||||
map = 'smap'
|
||||
var handleSTOP = function(err){
|
||||
// handle stop...
|
||||
stop = err
|
||||
if(err === that.constructor.STOP
|
||||
|| err instanceof that.constructor.STOP){
|
||||
return 'value' in err ?
|
||||
err.value
|
||||
: [] }
|
||||
throw err }
|
||||
try{
|
||||
return pack()
|
||||
}catch(err){
|
||||
return handleSTOP(err) } }
|
||||
|
||||
// pack (non-stoppable)...
|
||||
return pack() },
|
||||
// transform/handle packed array (sync, but can return promises in the list)...
|
||||
__handle: function(list, handler=undefined, onerror=undefined){
|
||||
var that = this
|
||||
if(typeof(list) == 'function'){
|
||||
handler = list
|
||||
list = this.__packed }
|
||||
if(!handler){
|
||||
return list }
|
||||
// handle promise list...
|
||||
if(list instanceof Promise){
|
||||
return list.then(function(list){
|
||||
return that.__handle(list, handler, onerror) }) }
|
||||
// do the work...
|
||||
// NOTE: since each section of the packed .__array is the same
|
||||
// structure as the input we'll use .__pack(..) to handle
|
||||
// them, this also keeps all the handling code in one place.
|
||||
var map = !!this.constructor.STOP ?
|
||||
'smap'
|
||||
: 'map'
|
||||
return list[map](function(elem){
|
||||
elem = elem instanceof Array
|
||||
|| elem instanceof Promise ?
|
||||
that.__pack(elem, handler, onerror)
|
||||
: [handler(elem)]
|
||||
elem = elem instanceof Promise ?
|
||||
elem.then(function([e]){
|
||||
return e })
|
||||
: elem
|
||||
return elem })
|
||||
.flat() },
|
||||
/*/
|
||||
__pack: function(list, handler=undefined, onerror=undefined){
|
||||
var that = this
|
||||
// handle iterator...
|
||||
@ -296,9 +165,12 @@ object.Constructor('IterablePromise', Promise, {
|
||||
.map(function(elem){
|
||||
return elem instanceof Array ?
|
||||
[elem]
|
||||
/* XXX PROMISE_WRAP
|
||||
/*/
|
||||
: elem instanceof Promise ?
|
||||
elem.then(function(e){
|
||||
return [e] })
|
||||
//*/
|
||||
: elem })
|
||||
// handle if needed...
|
||||
return handler ?
|
||||
@ -354,7 +226,13 @@ object.Constructor('IterablePromise', Promise, {
|
||||
// NOTE: the promise protects this from .flat()
|
||||
elem.then(function(elem){
|
||||
return !stop ?
|
||||
// XXX this should be the same as the non-promise version...
|
||||
// (see: .filter(..))
|
||||
/* XXX PROMISE_WRAP
|
||||
[each(elem)]
|
||||
/*/
|
||||
each(elem)
|
||||
//*/
|
||||
: [] })
|
||||
: elem instanceof Array ?
|
||||
[each(elem)]
|
||||
@ -363,7 +241,6 @@ object.Constructor('IterablePromise', Promise, {
|
||||
function(){
|
||||
stop = true })
|
||||
.flat() },
|
||||
//*/
|
||||
// XXX this should return IterablePromise if .__packed is partially sync (???)
|
||||
// unpack array (sync/async)...
|
||||
__unpack: function(list){
|
||||
@ -386,8 +263,11 @@ object.Constructor('IterablePromise', Promise, {
|
||||
// XXX can we return an IterablePromise???
|
||||
// XXX is there a more elegant way to do this???
|
||||
return Promise.all(list)
|
||||
/* XXX PROMISE_WRAP
|
||||
/*/
|
||||
.then(function(list){
|
||||
return list.flat() })
|
||||
//*/
|
||||
.iter() }
|
||||
res.push(e) }
|
||||
return res.flat() },
|
||||
@ -415,22 +295,40 @@ object.Constructor('IterablePromise', Promise, {
|
||||
map: function(func){
|
||||
return this.constructor(this,
|
||||
function(e){
|
||||
/* XXX PROMISE_WRAP
|
||||
var res = func(e)
|
||||
return res instanceof Promise ?
|
||||
res.then(function(e){
|
||||
res.then(function(e){
|
||||
return [e] })
|
||||
: [res] }) },
|
||||
/*/
|
||||
return [func(e)] }) },
|
||||
//*/
|
||||
// XXX BUG:
|
||||
// await Promise.iter([1, [2], 3])
|
||||
// .filter(e => Promise.resolve(false))
|
||||
// -> [ [] ]
|
||||
// should be:
|
||||
// -> []
|
||||
// ...do we flatten the result of promise returned by handler???
|
||||
// XXX this might require a change in .__handle(..)
|
||||
filter: function(func){
|
||||
return this.constructor(this,
|
||||
function(e){
|
||||
var res = func(e)
|
||||
var _filter = function(elem){
|
||||
return res ?
|
||||
[elem]
|
||||
: [] }
|
||||
return res instanceof Promise ?
|
||||
res.then(_filter)
|
||||
: _filter(e) }) },
|
||||
res.then(function(res){
|
||||
// XXX this should be the same as the non-promise version...
|
||||
return res ?
|
||||
/* XXX PROMISE_WRAP
|
||||
[e]
|
||||
/*/
|
||||
e
|
||||
//*/
|
||||
: [] })
|
||||
: res ?
|
||||
[e]
|
||||
: [] }) },
|
||||
// NOTE: this does not return an iterable promise as we can't know
|
||||
// what the user reduces to...
|
||||
// NOTE: the items can be handled out of order because the nested
|
||||
@ -861,6 +759,9 @@ object.Constructor('IterableSequentialPromise', IterablePromise, {
|
||||
&& i < list.length-1){
|
||||
res.push(e
|
||||
.then(function(e){
|
||||
// NOTE: this does not call any handlers, thus
|
||||
// there should be no risk of out of order
|
||||
// handler execution....
|
||||
return seqiter(
|
||||
[e, ...list.slice(i+1)])
|
||||
.flat() }))
|
||||
@ -873,6 +774,7 @@ object.Constructor('IterableSequentialPromise', IterablePromise, {
|
||||
list = list instanceof SyncPromise ?
|
||||
list.sync()
|
||||
: list
|
||||
// repack...
|
||||
list = list instanceof Array ?
|
||||
repack(list)
|
||||
: list.then ?
|
||||
|
||||
16
package-lock.json
generated
16
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "ig-types",
|
||||
"version": "6.24.11",
|
||||
"version": "6.24.16",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ig-types",
|
||||
"version": "6.24.11",
|
||||
"version": "6.24.16",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"ig-object": "^6.0.0",
|
||||
@ -359,9 +359,9 @@
|
||||
"integrity": "sha512-KxS8AGsjelRAmbbQuASj+XRuk99P4OOprd+lIUMU2nuRKPQItNQK/apls8IlR3kNp5ZdQqBdV+zVJmYGrxofnA=="
|
||||
},
|
||||
"node_modules/ig-test": {
|
||||
"version": "1.5.4",
|
||||
"resolved": "https://registry.npmjs.org/ig-test/-/ig-test-1.5.4.tgz",
|
||||
"integrity": "sha512-1N2U3v6tSPGUeBNnCuFWem09ngNkuMT1NGEEyVtA73VR5nz8GMbroifiPX0+j/GLqBJ/u39bsMCdZSMaIMTRdg==",
|
||||
"version": "1.5.9",
|
||||
"resolved": "https://registry.npmjs.org/ig-test/-/ig-test-1.5.9.tgz",
|
||||
"integrity": "sha512-6X/bO7yYh7B+DEJEFEVCQAwECs/EPr64h3V8xJbn69lWNBeSo08dkXEYdPkgU8sXDjZOh3cfvz7hcREnZHjpSQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"colors": "1.4.0",
|
||||
@ -1078,9 +1078,9 @@
|
||||
"integrity": "sha512-KxS8AGsjelRAmbbQuASj+XRuk99P4OOprd+lIUMU2nuRKPQItNQK/apls8IlR3kNp5ZdQqBdV+zVJmYGrxofnA=="
|
||||
},
|
||||
"ig-test": {
|
||||
"version": "1.5.4",
|
||||
"resolved": "https://registry.npmjs.org/ig-test/-/ig-test-1.5.4.tgz",
|
||||
"integrity": "sha512-1N2U3v6tSPGUeBNnCuFWem09ngNkuMT1NGEEyVtA73VR5nz8GMbroifiPX0+j/GLqBJ/u39bsMCdZSMaIMTRdg==",
|
||||
"version": "1.5.9",
|
||||
"resolved": "https://registry.npmjs.org/ig-test/-/ig-test-1.5.9.tgz",
|
||||
"integrity": "sha512-6X/bO7yYh7B+DEJEFEVCQAwECs/EPr64h3V8xJbn69lWNBeSo08dkXEYdPkgU8sXDjZOh3cfvz7hcREnZHjpSQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"colors": "1.4.0",
|
||||
|
||||
60
test.js
60
test.js
@ -112,9 +112,9 @@ var cases = test.Cases({
|
||||
},
|
||||
|
||||
IterablePromise: test.TestSet(function(){
|
||||
var create = function(assert, value){
|
||||
var create = function(assert, value, expected){
|
||||
return {
|
||||
input: value,
|
||||
input: expected ?? value,
|
||||
output: assert(Promise.iter(value), 'Promise.iter(', value, ')'),
|
||||
} }
|
||||
|
||||
@ -136,21 +136,17 @@ var cases = test.Cases({
|
||||
array_mixed: function(assert){
|
||||
return create(assert, [1, Promise.resolve(2), 3]) },
|
||||
nested_array_mixed: function(assert){
|
||||
return create(assert, [
|
||||
1,
|
||||
Promise.resolve(2),
|
||||
[3],
|
||||
Promise.resolve([4]),
|
||||
]) },
|
||||
return create(assert,
|
||||
[1, Promise.resolve(2), [3], Promise.resolve([4])],
|
||||
[1, 2, [3], [4]]) },
|
||||
promise_array_mixed: function(assert){
|
||||
return create(assert, Promise.resolve([1, Promise.resolve(2), 3])) },
|
||||
return create(assert,
|
||||
Promise.resolve([1, Promise.resolve(2), 3]),
|
||||
[1, 2, 3]) },
|
||||
promise_nested_array_mixed: function(assert){
|
||||
return create(assert, Promise.resolve([
|
||||
1,
|
||||
Promise.resolve(2),
|
||||
[3],
|
||||
Promise.resolve([4]),
|
||||
])) },
|
||||
return create(assert,
|
||||
Promise.resolve([1, Promise.resolve(2), [3], Promise.resolve([4])]),
|
||||
[1, 2, [3], [4]]) },
|
||||
})
|
||||
this.Modifier({
|
||||
nest: function(assert, setup){
|
||||
@ -182,6 +178,19 @@ var cases = test.Cases({
|
||||
output: setup.output
|
||||
.filter(function(e){ return false }),
|
||||
} },
|
||||
filter_promise_all: function(assert, setup){
|
||||
setup.output = setup.output
|
||||
.filter(function(e){
|
||||
return Promise.resolve(true) })
|
||||
return setup },
|
||||
filter_promise_none: function(assert, setup){
|
||||
return {
|
||||
input: [],
|
||||
output: setup.output
|
||||
.filter(function(e){
|
||||
return Promise.resolve(false) }),
|
||||
} },
|
||||
//*/
|
||||
|
||||
/* XXX need tuning...
|
||||
concat_basic: function(assert, {input, output}){
|
||||
@ -300,6 +309,23 @@ var cases = test.Cases({
|
||||
[1,2,3],
|
||||
'flat unpack', meth)
|
||||
}
|
||||
|
||||
var order = []
|
||||
await Promise.seqiter([
|
||||
1,
|
||||
Promise.resolve(2),
|
||||
Promise.all([3,4]),
|
||||
Promise.seqiter([5]),
|
||||
6,
|
||||
])
|
||||
.flat()
|
||||
.map(function(e){
|
||||
order.push(e)
|
||||
return e })
|
||||
assert.array(
|
||||
order,
|
||||
[1,2,3,4,5,6],
|
||||
'Promise.seqiter(..) handle order')
|
||||
},
|
||||
|
||||
// Date.js
|
||||
@ -557,8 +583,8 @@ Events.cases({
|
||||
|
||||
|
||||
// test event list...
|
||||
assert.array(obj.events, ['event', 'eventBlank'], '.events')
|
||||
assert.array(obj.eventful, ['bareEvent', 'bareEventBlank'], '.eventful')
|
||||
assert.array(obj.events, ['eventBlank', 'event'], '.events')
|
||||
assert.array(obj.eventful, ['bareEventBlank', 'bareEvent'], '.eventful')
|
||||
|
||||
// bind...
|
||||
var bind = function(evt){
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user