mergeiterator
Advanced tools
Comparing version 1.2.5 to 1.3.0
@@ -1,8 +0,11 @@ | ||
## [1.2.5](https://github.com/vadzim/mergeiterator/compare/v1.2.4...v1.2.5) (2019-05-23) | ||
## 1.3.0 | ||
enhancement: | ||
* added typescript typings | ||
## [1.2.4](https://github.com/vadzim/mergeiterator/compare/v1.2.3...v1.2.4) (2019-05-17) | ||
* accept promise of iterable as a root sequence | ||
fix: | ||
* fixed leak of closing iterables when root sequence contains not an iterable |
@@ -13,4 +13,7 @@ "use strict"; | ||
require("./polyfills/symbolAsyncIterator.js"); | ||
var _mergeiterator = require("./mergeiterator.js"); | ||
module.exports = exports.default; | ||
module.exports = exports.default; | ||
module.exports.default = exports.default; |
@@ -8,4 +8,2 @@ "use strict"; | ||
require("./symbolAsyncIterator.js"); | ||
function _awaitAsyncGenerator(value) { return new _AwaitValue(value); } | ||
@@ -15,3 +13,3 @@ | ||
function _AsyncGenerator(gen) { var front, back; function send(key, arg) { return new Promise(function (resolve, reject) { var request = { key: key, arg: arg, resolve: resolve, reject: reject, next: null }; if (back) { back = back.next = request; } else { front = back = request; resume(key, arg); } }); } function resume(key, arg) { try { var result = gen[key](arg); var value = result.value; var wrappedAwait = value instanceof _AwaitValue; Promise.resolve(wrappedAwait ? value.wrapped : value).then(function (arg) { if (wrappedAwait) { resume("next", arg); return; } settle(result.done ? "return" : "normal", arg); }, function (err) { resume("throw", err); }); } catch (err) { settle("throw", err); } } function settle(type, value) { switch (type) { case "return": front.resolve({ value: value, done: true }); break; case "throw": front.reject(value); break; default: front.resolve({ value: value, done: false }); break; } front = front.next; if (front) { resume(front.key, front.arg); } else { back = null; } } this._invoke = send; if (typeof gen.return !== "function") { this.return = undefined; } } | ||
function _AsyncGenerator(gen) { var front, back; function send(key, arg) { return new Promise(function (resolve, reject) { var request = { key: key, arg: arg, resolve: resolve, reject: reject, next: null }; if (back) { back = back.next = request; } else { front = back = request; resume(key, arg); } }); } function resume(key, arg) { try { var result = gen[key](arg); var value = result.value; var wrappedAwait = value instanceof _AwaitValue; Promise.resolve(wrappedAwait ? value.wrapped : value).then(function (arg) { if (wrappedAwait) { resume(key === "return" ? "return" : "next", arg); return; } settle(result.done ? "return" : "normal", arg); }, function (err) { resume("throw", err); }); } catch (err) { settle("throw", err); } } function settle(type, value) { switch (type) { case "return": front.resolve({ value: value, done: true }); break; case "throw": front.reject(value); break; default: front.resolve({ value: value, done: false }); break; } front = front.next; if (front) { resume(front.key, front.arg); } else { back = null; } } this._invoke = send; if (typeof gen.return !== "function") { this.return = undefined; } } | ||
@@ -28,5 +26,2 @@ if (typeof Symbol === "function" && Symbol.asyncIterator) { _AsyncGenerator.prototype[Symbol.asyncIterator] = function () { return this; }; } | ||
/** | ||
* Merges async or sync iterables into async one. | ||
*/ | ||
function merge(_x) { | ||
@@ -38,9 +33,10 @@ return _merge.apply(this, arguments); | ||
_merge = _wrapAsyncGenerator(function* (sequences) { | ||
const rootIterator = getIterator(sequences); | ||
const readers = [readRootIterator]; | ||
const valueGetters = []; | ||
const rootIterator = getIterator((yield _awaitAsyncGenerator(sequences))); | ||
const ticks = [readRootIterator]; | ||
const getters = []; | ||
let iteratorsCount = 1; // There is only rootIterator opened so far. | ||
let mergeDone = false; | ||
let onData; | ||
let onStateChanged; // should be called whenever values used in the main `while` loop have been changed. These are: iteratorsCount, ticks and getters | ||
let normalReturn = true; | ||
@@ -51,9 +47,9 @@ let rootReturnResult; | ||
while (iteratorsCount > 0) { | ||
const dataPresent = new Promise(setOnData); | ||
const stateChanged = new Promise(setOnStateChanged); | ||
while (readers.length) readers.shift()(); | ||
while (ticks.length) ticks.shift()(); | ||
yield _awaitAsyncGenerator(dataPresent); | ||
yield _awaitAsyncGenerator(stateChanged); | ||
while (valueGetters.length > 0) yield valueGetters.shift()(); | ||
while (getters.length > 0) yield getters.shift()(); | ||
} | ||
@@ -67,7 +63,7 @@ } catch (e) { | ||
while (iteratorsCount > 0) { | ||
const dataPresent = new Promise(setOnData); | ||
const stateChanged = new Promise(setOnStateChanged); | ||
while (readers.length) readers.shift()(); | ||
while (ticks.length) ticks.shift()(); | ||
yield _awaitAsyncGenerator(dataPresent); | ||
yield _awaitAsyncGenerator(stateChanged); | ||
} // Do not hide an exception if it's been already raised. | ||
@@ -78,3 +74,3 @@ | ||
// Raise possible exceptions on iterators interruption. | ||
while (valueGetters.length > 0) valueGetters.shift()(); // There is no chance to return a value out of finally block if .return() is called. | ||
while (getters.length > 0) getters.shift()(); // There is no chance to return a value out of finally block if .return() is called. | ||
// eslint-disable-next-line no-unsafe-finally | ||
@@ -90,20 +86,6 @@ | ||
function setOnData(resolve) { | ||
onData = resolve; | ||
function setOnStateChanged(resolve) { | ||
onStateChanged = resolve; | ||
} | ||
function throwError(error) { | ||
iteratorsCount--; | ||
valueGetters.push(() => { | ||
throw error; | ||
}); | ||
mergeDone = true; | ||
onData(); | ||
} | ||
function iteratorStopped() { | ||
iteratorsCount--; | ||
onData(); | ||
} | ||
function stopRootIterator() { | ||
@@ -115,8 +97,26 @@ stopIterator(rootIterator).then(({ | ||
if (done) rootReturnResult = value; | ||
iteratorStopped(); | ||
}, error => throwError(error)); | ||
iteratorsCount--; | ||
onStateChanged(); | ||
}, error => { | ||
getters.push(() => { | ||
throw error; | ||
}); | ||
mergeDone = true; | ||
iteratorsCount--; | ||
onStateChanged(); | ||
}); | ||
} | ||
function stopChildIterator(iterator) { | ||
stopIterator(iterator).then(() => iteratorStopped(), error => throwError(error)); | ||
stopIterator(iterator).then(() => { | ||
iteratorsCount--; | ||
onStateChanged(); | ||
}, error => { | ||
getters.push(() => { | ||
throw error; | ||
}); | ||
mergeDone = true; | ||
iteratorsCount--; | ||
onStateChanged(); | ||
}); | ||
} | ||
@@ -136,3 +136,4 @@ | ||
rootReturnResult = value; | ||
iteratorStopped(); | ||
iteratorsCount--; | ||
onStateChanged(); | ||
return; | ||
@@ -146,9 +147,13 @@ } | ||
let iterator; | ||
let childIterator; | ||
try { | ||
iterator = getIterator(value); | ||
} catch (e) { | ||
throwError(e); | ||
childIterator = getIterator(value); | ||
} catch (error) { | ||
stopRootIterator(); | ||
getters.push(() => { | ||
throw error; | ||
}); | ||
mergeDone = true; | ||
onStateChanged(); | ||
return; | ||
@@ -158,6 +163,13 @@ } | ||
iteratorsCount++; | ||
readers.push(getChildReader(iterator)); | ||
readers.push(readRootIterator); | ||
onData(); | ||
}, error => throwError(error)); | ||
ticks.push(readRootIterator); | ||
ticks.push(getChildReader(childIterator)); | ||
onStateChanged(); | ||
}, error => { | ||
getters.push(() => { | ||
throw error; | ||
}); | ||
mergeDone = true; | ||
iteratorsCount--; | ||
onStateChanged(); | ||
}); | ||
} | ||
@@ -177,3 +189,4 @@ | ||
if (done) { | ||
iteratorStopped(); | ||
iteratorsCount--; | ||
onStateChanged(); | ||
return; | ||
@@ -187,6 +200,13 @@ } | ||
readers.push(readChildIterator); | ||
valueGetters.push(() => value); | ||
onData(); | ||
}, error => throwError(error)); | ||
ticks.push(readChildIterator); | ||
getters.push(() => value); | ||
onStateChanged(); | ||
}, error => { | ||
getters.push(() => { | ||
throw error; | ||
}); | ||
mergeDone = true; | ||
iteratorsCount--; | ||
onStateChanged(); | ||
}); | ||
}; | ||
@@ -200,4 +220,3 @@ } | ||
const method = iterable[Symbol.asyncIterator] || iterable[Symbol.iterator]; | ||
if (method) return method.call(iterable); | ||
if (typeof iterable.next === "function") return iterable; // eslint-disable-next-line no-unused-vars | ||
if (method) return method.call(iterable); // eslint-disable-next-line no-unused-vars | ||
@@ -204,0 +223,0 @@ for ( |
{ | ||
"name": "mergeiterator", | ||
"version": "1.2.5", | ||
"version": "1.3.0", | ||
"description": "merges async iterators", | ||
@@ -8,2 +8,3 @@ "license": "MIT", | ||
"main": "dist/index.js", | ||
"types": "src/index.d.ts", | ||
"bugs": { | ||
@@ -26,3 +27,3 @@ "url": "https://github.com/vadzim/mergeiterator/issues" | ||
"flow": "flow check", | ||
"flowinstall": "flow-typed install --ignoreDeps=dev", | ||
"flowinstall": "flow-typed install --ignoreDeps=dev; flow-typed install jest", | ||
"docs": "documentation --config documentation.yml readme src --section=API", | ||
@@ -35,3 +36,2 @@ "postdocs": "git add README.md", | ||
"preversion": "npm run flowinstall && npm run lint && npm test && npm run build", | ||
"version": "standard-changelog && git add CHANGELOG.md", | ||
"postpublish": "git push origin master --follow-tags", | ||
@@ -52,36 +52,36 @@ "codecov": "codecov --token=$CODECOV_TOKEN" | ||
], | ||
"dependencies": {}, | ||
"dependencies": { | ||
"type-any-iterable": "^1.0.3" | ||
}, | ||
"peerDependencies": {}, | ||
"devDependencies": { | ||
"@babel/cli": "^7.4.4", | ||
"@babel/core": "^7.4.4", | ||
"@babel/plugin-proposal-class-properties": "^7.4.4", | ||
"@babel/plugin-proposal-decorators": "^7.4.4", | ||
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.4.4", | ||
"@babel/plugin-proposal-numeric-separator": "^7.2.0", | ||
"@babel/plugin-proposal-optional-chaining": "^7.2.0", | ||
"@babel/plugin-proposal-pipeline-operator": "^7.3.2", | ||
"@babel/preset-env": "^7.4.4", | ||
"@babel/preset-flow": "^7.0.0", | ||
"babel-eslint": "^10.0.1", | ||
"babel-jest": "^24.8.0", | ||
"@babel/cli": "^7.7.7", | ||
"@babel/core": "^7.7.7", | ||
"@babel/plugin-proposal-class-properties": "^7.7.4", | ||
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.7.4", | ||
"@babel/plugin-proposal-numeric-separator": "^7.7.4", | ||
"@babel/plugin-proposal-optional-chaining": "^7.7.5", | ||
"@babel/plugin-proposal-pipeline-operator": "^7.7.7", | ||
"@babel/preset-env": "^7.7.7", | ||
"@babel/preset-flow": "^7.7.4", | ||
"babel-eslint": "^10.0.3", | ||
"babel-jest": "^24.9.0", | ||
"babel-plugin-add-module-exports": "^1.0.2", | ||
"codecov": "^3.5.0", | ||
"documentation": "^11.0.0", | ||
"eslint": "^5.16.0", | ||
"eslint-config-airbnb-base": "^13.1.0", | ||
"eslint-config-prettier": "^4.2.0", | ||
"eslint-plugin-flowtype": "^3.8.2", | ||
"codecov": "^3.6.1", | ||
"documentation": "^12.1.4", | ||
"eslint": "^6.8.0", | ||
"eslint-config-airbnb-base": "^14.0.0", | ||
"eslint-config-prettier": "^6.9.0", | ||
"eslint-plugin-flowtype": "^4.5.2", | ||
"eslint-plugin-flowtype-errors": "^4.1.0", | ||
"eslint-plugin-import": "^2.17.2", | ||
"eslint-plugin-prettier": "^3.1.0", | ||
"flow-bin": "^0.98.1", | ||
"flow-copy-source": "^2.0.6", | ||
"flow-typed": "^2.5.2", | ||
"jest": "^24.8.0", | ||
"eslint-plugin-import": "^2.19.1", | ||
"eslint-plugin-prettier": "^3.1.2", | ||
"flow-bin": "^0.114.0", | ||
"flow-copy-source": "^2.0.9", | ||
"flow-typed": "^2.6.2", | ||
"jest": "^24.9.0", | ||
"lint-changed": "0.0.0-development", | ||
"prettier": "^1.17.1", | ||
"rimraf": "^2.6.3", | ||
"standard-changelog": "^2.0.11" | ||
"prettier": "^1.19.1", | ||
"rimraf": "^3.0.0" | ||
} | ||
} |
@@ -18,13 +18,18 @@ # mergeiterator | ||
async function DoIt() { | ||
const array = [1, 2, 3, 4, 5] | ||
const promisedArray = Promise.resolve([6, Promise.resolve(7)]) | ||
function *generator() { | ||
let i = 10 | ||
while (true) yield (i++) | ||
} | ||
async function *asyncGenerator() { | ||
yield 8 | ||
yield Promise.resolve(9) | ||
} | ||
for await (const v of merge([array, promisedArray, generator(), asyncGenerator()])) { | ||
for await (const v of merge([ | ||
[1, 2, Promise.resolve(3)], | ||
Promise.resolve([4, 5]), | ||
(function*() { | ||
let i = 9 | ||
while (true) { | ||
yield i++ | ||
yield Promise.resolve(i++) | ||
} | ||
})(), | ||
(async function*() { | ||
yield 6 | ||
yield await Promise.resolve(7) | ||
yield Promise.resolve(8) | ||
})(), | ||
])) { | ||
console.log(v) | ||
@@ -34,3 +39,3 @@ } | ||
// 1 2 6 3 7 10 4 11 8 5 12 9 13 14 15 ... | ||
// 1 4 2 9 5 3 10 6 11 7 12 8 13 14 15 16 17 18 19 20 ... | ||
``` | ||
@@ -37,0 +42,0 @@ |
// @flow | ||
import "./polyfills/symbolAsyncIterator.js" | ||
// eslint-disable-next-line import/no-default-export | ||
export { merge as default } from "./mergeiterator.js" |
// @flow | ||
import "./symbolAsyncIterator.js" | ||
import { type AnyIterable } from "type-any-iterable" | ||
type AnyIterable<T, ReturnT = *> = $AsyncIterable<Promise<T> | T, ReturnT, void> | $Iterable<Promise<T> | T, ReturnT, void> | ||
/** | ||
@@ -11,8 +9,8 @@ * Merges async or sync iterables into async one. | ||
export async function* merge<T, ReturnT>(sequences: AnyIterable<AnyIterable<T>, ReturnT>): AsyncGenerator<T, ReturnT, void> { | ||
const rootIterator = getIterator(sequences) | ||
const readers = [readRootIterator] | ||
const valueGetters = [] | ||
const rootIterator = getIterator(await sequences) | ||
const ticks = [readRootIterator] | ||
const getters = [] | ||
let iteratorsCount = 1 // There is only rootIterator opened so far. | ||
let mergeDone = false | ||
let onData | ||
let onStateChanged // should be called whenever values used in the main `while` loop have been changed. These are: iteratorsCount, ticks and getters | ||
let normalReturn = true | ||
@@ -23,6 +21,6 @@ let rootReturnResult | ||
while (iteratorsCount > 0) { | ||
const dataPresent = new Promise(setOnData) | ||
while (readers.length) readers.shift()() | ||
await dataPresent | ||
while (valueGetters.length > 0) yield valueGetters.shift()() | ||
const stateChanged = new Promise(setOnStateChanged) | ||
while (ticks.length) ticks.shift()() | ||
await stateChanged | ||
while (getters.length > 0) yield getters.shift()() | ||
} | ||
@@ -35,5 +33,5 @@ } catch (e) { | ||
while (iteratorsCount > 0) { | ||
const dataPresent = new Promise(setOnData) | ||
while (readers.length) readers.shift()() | ||
await dataPresent | ||
const stateChanged = new Promise(setOnStateChanged) | ||
while (ticks.length) ticks.shift()() | ||
await stateChanged | ||
} | ||
@@ -43,3 +41,3 @@ // Do not hide an exception if it's been already raised. | ||
// Raise possible exceptions on iterators interruption. | ||
while (valueGetters.length > 0) valueGetters.shift()() | ||
while (getters.length > 0) getters.shift()() | ||
// There is no chance to return a value out of finally block if .return() is called. | ||
@@ -54,20 +52,6 @@ // eslint-disable-next-line no-unsafe-finally | ||
function setOnData(resolve) { | ||
onData = resolve | ||
function setOnStateChanged(resolve) { | ||
onStateChanged = resolve | ||
} | ||
function throwError(error) { | ||
iteratorsCount-- | ||
valueGetters.push(() => { | ||
throw error | ||
}) | ||
mergeDone = true | ||
onData() | ||
} | ||
function iteratorStopped() { | ||
iteratorsCount-- | ||
onData() | ||
} | ||
function stopRootIterator() { | ||
@@ -77,5 +61,13 @@ stopIterator(rootIterator).then( | ||
if (done) rootReturnResult = value | ||
iteratorStopped() | ||
iteratorsCount-- | ||
onStateChanged() | ||
}, | ||
error => throwError(error), | ||
error => { | ||
getters.push(() => { | ||
throw error | ||
}) | ||
mergeDone = true | ||
iteratorsCount-- | ||
onStateChanged() | ||
}, | ||
) | ||
@@ -85,3 +77,16 @@ } | ||
function stopChildIterator(iterator) { | ||
stopIterator(iterator).then(() => iteratorStopped(), error => throwError(error)) | ||
stopIterator(iterator).then( | ||
() => { | ||
iteratorsCount-- | ||
onStateChanged() | ||
}, | ||
error => { | ||
getters.push(() => { | ||
throw error | ||
}) | ||
mergeDone = true | ||
iteratorsCount-- | ||
onStateChanged() | ||
}, | ||
) | ||
} | ||
@@ -98,3 +103,4 @@ | ||
rootReturnResult = value | ||
iteratorStopped() | ||
iteratorsCount-- | ||
onStateChanged() | ||
return | ||
@@ -106,16 +112,27 @@ } | ||
} | ||
let iterator | ||
let childIterator | ||
try { | ||
iterator = getIterator(value) | ||
} catch (e) { | ||
throwError(e) | ||
childIterator = getIterator(value) | ||
} catch (error) { | ||
stopRootIterator() | ||
getters.push(() => { | ||
throw error | ||
}) | ||
mergeDone = true | ||
onStateChanged() | ||
return | ||
} | ||
iteratorsCount++ | ||
readers.push(getChildReader(iterator)) | ||
readers.push(readRootIterator) | ||
onData() | ||
ticks.push(readRootIterator) | ||
ticks.push(getChildReader(childIterator)) | ||
onStateChanged() | ||
}, | ||
error => throwError(error), | ||
error => { | ||
getters.push(() => { | ||
throw error | ||
}) | ||
mergeDone = true | ||
iteratorsCount-- | ||
onStateChanged() | ||
}, | ||
) | ||
@@ -133,3 +150,4 @@ } | ||
if (done) { | ||
iteratorStopped() | ||
iteratorsCount-- | ||
onStateChanged() | ||
return | ||
@@ -141,7 +159,14 @@ } | ||
} | ||
readers.push(readChildIterator) | ||
valueGetters.push(() => (value: any)) | ||
onData() | ||
ticks.push(readChildIterator) | ||
getters.push(() => (value: any)) | ||
onStateChanged() | ||
}, | ||
error => throwError(error), | ||
error => { | ||
getters.push(() => { | ||
throw error | ||
}) | ||
mergeDone = true | ||
iteratorsCount-- | ||
onStateChanged() | ||
}, | ||
) | ||
@@ -155,3 +180,2 @@ } | ||
if (method) return (method.call(iterable): any) | ||
if (typeof iterable.next === "function") return iterable | ||
// eslint-disable-next-line no-unused-vars | ||
@@ -158,0 +182,0 @@ for (/* should throw here */ const x of iterable) { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
23188
28
14
405
68
1
+ Addedtype-any-iterable@^1.0.3
+ Addedtype-any-iterable@1.0.5(transitive)
+ Addedtype-async-value@1.0.4(transitive)