callbag-flatten
Advanced tools
Comparing version
@@ -5,12 +5,10 @@ 'use strict'; | ||
if (start !== 0) return; | ||
const exists = x => typeof x !== 'undefined'; | ||
const absent = x => typeof x === 'undefined'; | ||
let outerEnded = false; | ||
let outerTalkback; | ||
let innerTalkback; | ||
function talkback(t,d) { | ||
if (t === 1) (innerTalkback || outerTalkback)(1,d); | ||
function talkback(t, d) { | ||
if (t === 1) (innerTalkback || outerTalkback)(1, d); | ||
if (t === 2) { | ||
innerTalkback && innerTalkback(2); | ||
outerTalkback && outerTalkback(2); | ||
outerTalkback(2); | ||
} | ||
@@ -24,3 +22,3 @@ } | ||
const innerSource = D; | ||
if (innerTalkback) innerTalkback(2); | ||
innerTalkback && innerTalkback(2); | ||
innerSource(0, (t, d) => { | ||
@@ -31,3 +29,6 @@ if (t === 0) { | ||
} else if (t === 1) sink(1, d); | ||
else if (t === 2 && absent(d)) { | ||
else if (t === 2 && d) { | ||
outerTalkback(2); | ||
sink(2, d); | ||
} else if (t === 2) { | ||
if (outerEnded) sink(2); | ||
@@ -39,8 +40,10 @@ else { | ||
} | ||
else if (t === 2 && exists(d)) sink(2, d); | ||
}); | ||
} else if (T === 2 && absent(D)) { | ||
} else if (T === 2 && D) { | ||
innerTalkback && innerTalkback(2); | ||
sink(2, D); | ||
} else if (T === 2) { | ||
if (!innerTalkback) sink(2); | ||
else outerEnded = true; | ||
} else if (T === 2 && exists(D)) sink(2, D); | ||
} | ||
}); | ||
@@ -47,0 +50,0 @@ }; |
23
index.js
const flatten = source => (start, sink) => { | ||
if (start !== 0) return; | ||
const exists = x => typeof x !== 'undefined'; | ||
const absent = x => typeof x === 'undefined'; | ||
let outerEnded = false; | ||
let outerTalkback; | ||
let innerTalkback; | ||
function talkback(t,d) { | ||
if (t === 1) (innerTalkback || outerTalkback)(1,d); | ||
function talkback(t, d) { | ||
if (t === 1) (innerTalkback || outerTalkback)(1, d); | ||
if (t === 2) { | ||
innerTalkback && innerTalkback(2); | ||
outerTalkback && outerTalkback(2); | ||
outerTalkback(2); | ||
} | ||
@@ -21,3 +19,3 @@ } | ||
const innerSource = D; | ||
if (innerTalkback) innerTalkback(2); | ||
innerTalkback && innerTalkback(2); | ||
innerSource(0, (t, d) => { | ||
@@ -28,3 +26,6 @@ if (t === 0) { | ||
} else if (t === 1) sink(1, d); | ||
else if (t === 2 && absent(d)) { | ||
else if (t === 2 && d) { | ||
outerTalkback(2); | ||
sink(2, d); | ||
} else if (t === 2) { | ||
if (outerEnded) sink(2); | ||
@@ -36,8 +37,10 @@ else { | ||
} | ||
else if (t === 2 && exists(d)) sink(2, d); | ||
}); | ||
} else if (T === 2 && absent(D)) { | ||
} else if (T === 2 && D) { | ||
innerTalkback && innerTalkback(2); | ||
sink(2, D); | ||
} else if (T === 2) { | ||
if (!innerTalkback) sink(2); | ||
else outerEnded = true; | ||
} else if (T === 2 && exists(D)) sink(2, D); | ||
} | ||
}); | ||
@@ -44,0 +47,0 @@ }; |
{ | ||
"name": "callbag-flatten", | ||
"version": "1.2.0", | ||
"version": "1.3.0", | ||
"description": "Callbag operator that flattens a higher-order callbag source", | ||
@@ -11,2 +11,3 @@ "repository": { | ||
"module": "index.js", | ||
"types": "types.d.ts", | ||
"scripts": { | ||
@@ -27,3 +28,6 @@ "build": "rollup $npm_package_module -o $npm_package_main --f cjs", | ||
"tape": "^4.8.0" | ||
}, | ||
"dependencies": { | ||
"callbag": "^1.1.0" | ||
} | ||
} |
212
test.js
@@ -179,1 +179,213 @@ const test = require('tape'); | ||
}); | ||
test('it should not treat falsy values as errors', t => { | ||
t.plan(23); | ||
const downwardsExpectedType = [ | ||
[0, 'function'], | ||
[1, 'string'], | ||
[1, 'string'], | ||
[1, 'string'], | ||
[1, 'string'], | ||
[1, 'string'], | ||
[1, 'string'], | ||
[2, 'undefined'] | ||
]; | ||
const downwardsExpected = ['a1', 'a2', 'b1', 'b2', 'b3', 'b4']; | ||
function sourceOuter(type, data) { | ||
if (type === 0) { | ||
const sink = data; | ||
setTimeout(() => { sink(1, 'a'); }, 230); | ||
setTimeout(() => { sink(1, 'b'); }, 460); | ||
setTimeout(() => { sink(2, null); }, 690); | ||
sink(0, sourceOuter); | ||
} | ||
} | ||
function sourceInner(type, data) { | ||
if (type === 0) { | ||
const sink = data; | ||
let i = 0; | ||
const id = setInterval(() => { | ||
i++; | ||
sink(1, i); | ||
if (i === 4) { | ||
clearInterval(id); | ||
sink(2); | ||
} | ||
}, 100); | ||
sink(0, (t, d) => { | ||
if (t === 2) clearInterval(id); | ||
}); | ||
} | ||
} | ||
function sink(type, data) { | ||
const et = downwardsExpectedType.shift(); | ||
t.equals(type, et[0], 'downwards type is expected: ' + et[0]); | ||
t.equals(typeof data, et[1], 'downwards data type is expected: ' + et[1]); | ||
if (type === 1) { | ||
const e = downwardsExpected.shift(); | ||
t.equals(data, e, 'downwards data is expected: ' + JSON.stringify(e)); | ||
} | ||
}; | ||
const source = flatten( | ||
map(str => | ||
map(num => str + num)(sourceInner) | ||
)(sourceOuter) | ||
); | ||
source(0, sink); | ||
setTimeout(() => { | ||
t.pass('nothing else happens'); | ||
t.end(); | ||
}, 1200); | ||
}); | ||
test('it errors sink & unsubscribe from inner when outer throws', t => { | ||
t.plan(21); | ||
const innerExpectedType = [ | ||
[0, 'function'], | ||
[0, 'function'], | ||
[2, 'undefined'], | ||
]; | ||
const downwardsExpectedType = [ | ||
[0, 'function'], | ||
[1, 'string'], | ||
[1, 'string'], | ||
[1, 'string'], | ||
[1, 'string'], | ||
[2, 'number'] | ||
]; | ||
const downwardsExpected = ['a1', 'a2', 'b1', 'b2']; | ||
function sourceOuter(type, data) { | ||
if (type === 0) { | ||
const sink = data; | ||
setTimeout(() => { sink(1, 'a'); }, 230); | ||
setTimeout(() => { sink(1, 'b'); }, 460); | ||
setTimeout(() => { sink(2, 42); }, 690); | ||
sink(0, sourceOuter); | ||
} | ||
} | ||
function sourceInner(type, data) { | ||
const et = innerExpectedType.shift(); | ||
t.equals(type, et[0], 'inner type is expected: ' + et[0]); | ||
t.equals(typeof data, et[1], 'inner data type is expected: ' + et[1]); | ||
if (type === 0) { | ||
const sink = data; | ||
let i = 0; | ||
const id = setInterval(() => { | ||
i++; | ||
sink(1, i); | ||
if (i === 4) { | ||
clearInterval(id); | ||
sink(2); | ||
} | ||
}, 100); | ||
sink(0, (t, d) => { | ||
if (t === 2) clearInterval(id); | ||
}); | ||
} | ||
} | ||
function sink(type, data) { | ||
const et = downwardsExpectedType.shift(); | ||
t.equals(type, et[0], 'downwards type is expected: ' + et[0]); | ||
t.equals(typeof data, et[1], 'downwards data type is expected: ' + et[1]); | ||
if (type === 1) { | ||
const e = downwardsExpected.shift(); | ||
t.equals(data, e, 'downwards data is expected: ' + JSON.stringify(e)); | ||
} | ||
}; | ||
const source = flatten( | ||
map(str => | ||
map(num => str + num)(sourceInner) | ||
)(sourceOuter) | ||
); | ||
source(0, sink); | ||
setTimeout(() => { | ||
t.pass('nothing else happens'); | ||
t.end(); | ||
}, 1200); | ||
}); | ||
test('it errors sink & unsubscribe from outer when inner throws', t => { | ||
t.plan(27); | ||
const outerExpectedType = [ | ||
[0, 'function'], | ||
[2, 'undefined'], | ||
]; | ||
const downwardsExpectedType = [ | ||
[0, 'function'], | ||
[1, 'string'], | ||
[1, 'string'], | ||
[1, 'string'], | ||
[1, 'string'], | ||
[1, 'string'], | ||
[1, 'string'], | ||
[2, 'number'] | ||
]; | ||
const downwardsExpected = ['a1', 'a2', 'b1', 'b2', 'b3', 'b4']; | ||
function sourceOuter(type, data) { | ||
const et = outerExpectedType.shift(); | ||
t.equals(type, et[0], 'outer type is expected: ' + et[0]); | ||
t.equals(typeof data, et[1], 'outer data type is expected: ' + et[1]); | ||
if (type === 0) { | ||
const sink = data; | ||
setTimeout(() => { sink(1, 'a'); }, 230); | ||
setTimeout(() => { sink(1, 'b'); }, 460); | ||
sink(0, sourceOuter); | ||
} | ||
} | ||
function sourceInner(type, data) { | ||
if (type === 0) { | ||
const sink = data; | ||
let i = 0; | ||
const id = setInterval(() => { | ||
i++; | ||
sink(1, i); | ||
if (i === 4) { | ||
clearInterval(id); | ||
sink(2, 42); | ||
} | ||
}, 100); | ||
sink(0, (t, d) => { | ||
if (t === 2) clearInterval(id); | ||
}); | ||
} | ||
} | ||
function sink(type, data) { | ||
const et = downwardsExpectedType.shift(); | ||
t.equals(type, et[0], 'downwards type is expected: ' + et[0]); | ||
t.equals(typeof data, et[1], 'downwards data type is expected: ' + et[1]); | ||
if (type === 1) { | ||
const e = downwardsExpected.shift(); | ||
t.equals(data, e, 'downwards data is expected: ' + JSON.stringify(e)); | ||
} | ||
}; | ||
const source = flatten( | ||
map(str => | ||
map(num => str + num)(sourceInner) | ||
)(sourceOuter) | ||
); | ||
source(0, sink); | ||
setTimeout(() => { | ||
t.pass('nothing else happens'); | ||
t.end(); | ||
}, 1200); | ||
}); |
14851
53.31%8
14.29%445
79.44%1
Infinity%+ Added
+ Added