├── .gitignore ├── .travis.yml ├── .jshintrc ├── bower.json ├── LICENSE.txt ├── CHANGELOG.md ├── package.json ├── gulpfile.js ├── test ├── inputs.js ├── single.js ├── arrays.js ├── inarrays.js ├── inobjects.js ├── objects.js └── multiple.js ├── index.js ├── dist ├── index.min.js ├── index.js └── maps │ └── index.min.js.map └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "5.4" 4 | - "5.3" 5 | - "5.2" 6 | - "5.1" 7 | - "5.0" 8 | - "4.2" 9 | - "4.1" 10 | - "4.0" 11 | - "node" 12 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "camelcase": true, 3 | "immed": true, 4 | "latedef": false, 5 | "newcap": true, 6 | "nonew": true, 7 | "plusplus": true, 8 | "quotmark": "single", 9 | "varstmt": true, 10 | "esnext": true, 11 | "browser": false, 12 | "devel": false, 13 | "node": true 14 | } 15 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "few", 3 | "main": "./dist/index.js", 4 | "version": "1.2.0", 5 | "homepage": "https://github.com/forter/few", 6 | "authors": [ 7 | "itay kimia ", 8 | "ori weingart ", 9 | "liron goldenberg " 10 | ], 11 | "description": "Write asynchronous code in a synchronous fashion", 12 | "keywords": [ 13 | "few" 14 | ], 15 | "license": "Apache 2.0", 16 | "ignore": [ 17 | ".*", 18 | "node_modules", 19 | "bower_components", 20 | "test", 21 | "tests" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2016 Forter 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | #Changelog 2 | ## v1.2.0 3 | 4 | * Support yielding array / object of generator functions without initiating them: 5 | ```javascript 6 | yield [myGeneratorFunction, myGeneratorFunction()]; // Both works! 7 | ``` 8 | 9 | * Support yielding generator functions and initialized generators with a simple `yield`: 10 | ```javascript 11 | // All of the below works! 12 | yield* myGeneratorFunction(); 13 | yield myGeneratorFunction; 14 | yield myGeneratorFunction(); 15 | ``` 16 | `yield*` is still preferable since it performs a native delegation. 17 | 18 | ## v1.1.0 19 | 20 | * Add browser support with browserify 21 | 22 | ## v1.0.0 23 | 24 | * Initial release 25 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "few", 3 | "version": "1.2.0", 4 | "description": "Write asynchronous code in a synchronous fashion", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "tape test/*" 8 | }, 9 | "keywords": [ 10 | "generator", 11 | "es6", 12 | "esnext", 13 | "promise", 14 | "thunk", 15 | "flow", 16 | "control" 17 | ], 18 | "repository": "forter/few", 19 | "engines": { 20 | "node": ">=4.0.0", 21 | "npm": "^2.14.2" 22 | }, 23 | "license": "Apache 2.0", 24 | "devDependencies": { 25 | "tape": "^4.4.0", 26 | "gulp": "~3.8.10", 27 | "vinyl-source-stream": "~1.1.0", 28 | "gulp-rename": "~1.2.2", 29 | "gulp-inject-string": "~1.1.0", 30 | "gulp-babel": "~6.1.1", 31 | "babel-preset-es2015": "6.3.13", 32 | "browserify": "~13.0.0", 33 | "gulp-uglify": "~1.5.1", 34 | "gulp-sourcemaps": "~1.6.0" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const browserify = require('browserify'); 4 | const rename = require('gulp-rename'); 5 | const gulp = require('gulp'); 6 | const source = require('vinyl-source-stream'); 7 | const inject = require('gulp-inject-string'); 8 | const fs = require('fs'); 9 | const babel = require('gulp-babel'); 10 | const uglify = require('gulp-uglify'); 11 | const sourcemaps = require('gulp-sourcemaps'); 12 | 13 | /** 14 | * Move main index.js to dist with babel transform to es2015 15 | * TODO: remove babel once FF is supporting let and class 16 | */ 17 | gulp.task('dist', function () { 18 | return gulp.src('index.js') 19 | .pipe(babel({ 20 | presets: ['es2015'] 21 | })) 22 | .pipe(gulp.dest('./dist/')); 23 | }); 24 | 25 | /** 26 | * Browserify code 27 | */ 28 | gulp.task('browserify' ,['dist'], function () { 29 | const b = browserify({ 30 | entries: './dist/index.js', 31 | standalone: 'few', 32 | debug: true, 33 | }); 34 | return b.bundle() 35 | .pipe(source('./index.js')) 36 | .pipe(gulp.dest('./dist/')); 37 | }); 38 | 39 | /** 40 | * Build minfiy code 41 | */ 42 | gulp.task('build' ,['browserify'], function () { 43 | return gulp.src('./dist/index.js') 44 | .pipe(sourcemaps.init()) 45 | .pipe(uglify({ preserveComments: 'license' })) 46 | .pipe(rename({ extname: '.min.js' })) 47 | .pipe(sourcemaps.write('maps')) 48 | .pipe(gulp.dest('./dist/')); 49 | }); 50 | -------------------------------------------------------------------------------- /test/inputs.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const test = require('tape'); 4 | 5 | const few = require('../index'); 6 | 7 | const expected = Symbol(); 8 | 9 | function testValue(genOrFn) { 10 | return function (t) { 11 | t.plan(1); 12 | few(genOrFn, (err, actual) => t.is(actual, expected)); 13 | }; 14 | } 15 | 16 | test('passing a generator function should pass value', 17 | testValue(function* () { return yield expected; })); 18 | 19 | test('passing a generator should pass value', 20 | testValue((function* () { return yield expected; }()))); 21 | 22 | test('not passing a callback generator should not fail', function (t) { 23 | t.plan(1); 24 | few(function* () { return yield t.pass(); }); 25 | }); 26 | 27 | function assertTypeError(t) { 28 | return function (err) { 29 | t.is(err.constructor, TypeError); 30 | t.is(err.message, 'genOrFn must be a generator or a generator function'); 31 | }; 32 | } 33 | 34 | const OPTIONS = [undefined, null, {}, 1, '']; 35 | test('passing a wrong type for generator and callback should trigger an error callback', function (t) { 36 | t.plan(OPTIONS.length * 2); 37 | const callback = assertTypeError(t); 38 | OPTIONS.forEach(o => few(o, callback)); 39 | }); 40 | 41 | test('passing a wrong type for generator and no callback should throw an error', function (t) { 42 | t.plan(OPTIONS.length * 2); 43 | process.on('uncaughtException', assertTypeError(t)); 44 | OPTIONS.forEach(few); 45 | process.nextTick(() => process.removeAllListeners('uncaughtException')); 46 | }); 47 | -------------------------------------------------------------------------------- /test/single.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const test = require('tape'); 4 | 5 | const few = require('../index'); 6 | 7 | function testSingleValue(resolving, rejecting) { 8 | return function (t) { 9 | const expected = Symbol(); 10 | t.plan(2); 11 | few(resolving(expected), (err, actual) => t.is(actual, expected)); 12 | few(rejecting(expected), (actual) => t.is(actual, expected)); 13 | }; 14 | } 15 | 16 | test('yielding a single promise', testSingleValue( 17 | function* resolving(v) { return yield Promise.resolve(v); }, 18 | function* rejecting(v) { yield Promise.reject(v); })); 19 | 20 | test('yielding a single generator function', testSingleValue( 21 | function* resolving(v) { return yield function* (){return v}; }, 22 | function* rejecting(v) { return yield function* (){throw v}; })); 23 | 24 | test('yielding a single initiated generator function', testSingleValue( 25 | function* resolving(v) { return yield function* (){return v}(); }, 26 | function* rejecting(v) { return yield function* (){throw v}(); })); 27 | 28 | test('delegating to a single generator function', testSingleValue( 29 | function* resolving(v) { return yield* function* (){return v}(); }, 30 | function* rejecting(v) { return yield* function* (){throw v}(); })); 31 | 32 | test('yielding a single function', testSingleValue( 33 | function* resolving(v) { return yield cb => process.nextTick(() => cb(null, v)); }, 34 | function* rejecting(v) { yield cb => process.nextTick(() => cb(v)); })); 35 | 36 | test('yielding a single synchronous function', testSingleValue( 37 | function* resolving(v) { return yield cb => cb(null, v); }, 38 | function* rejecting(v) { yield cb => cb(v); })); 39 | 40 | test('yielding a single value', testSingleValue( 41 | function* resolving(v) { return yield v; }, 42 | function* rejecting(v) { throw yield v; })); 43 | 44 | test('returning a single value', testSingleValue( 45 | function* resolving(v) { yield; return v; }, 46 | function* rejecting(v) { yield; throw v; })); 47 | -------------------------------------------------------------------------------- /test/arrays.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const test = require('tape'); 4 | 5 | const few = require('../index'); 6 | 7 | function testArray(resolving, rejecting) { 8 | return function (t) { 9 | const expected = [Symbol(), Symbol()]; 10 | t.plan(2); 11 | few(resolving(expected), (err, actual) => t.same(actual, expected)); 12 | few(rejecting(expected), (actual) => t.same(actual, expected[0])); 13 | }; 14 | } 15 | 16 | test('yielding an array of promises', testArray( 17 | function* resolving(c) { return yield [Promise.resolve(c[0]), Promise.resolve(c[1])]; }, 18 | function* rejecting(c) { yield [Promise.reject(c[0]), Promise.resolve(c[1])]; })); 19 | 20 | const resolvingFunction = v => cb => process.nextTick(() => cb(null, v)); 21 | const rejectingFunction = v => cb => process.nextTick(() => cb(v)); 22 | test('yielding an array of functions', testArray( 23 | function* resolving(c) { return yield [resolvingFunction(c[0]), resolvingFunction(c[1])]; }, 24 | function* rejecting(c) { yield [rejectingFunction(c[0]), resolvingFunction(c[1])]; })); 25 | 26 | test('yielding an array of values', testArray( 27 | function* resolving(c) { return yield c; }, 28 | function* rejecting(c) { throw yield c[0]; })); 29 | 30 | function* resolvingGenertor(v) { 31 | return yield resolvingFunction(v); 32 | } 33 | function* rejectingGenertor(v) { 34 | return yield rejectingFunction(v); 35 | } 36 | test('yielding an array of generators', testArray( 37 | function* resolving(c) { return yield [resolvingGenertor(c[0]), resolvingGenertor(c[1])]; }, 38 | function* rejecting(c) { yield [rejectingGenertor(c[0]), resolvingGenertor(c[1])]; })); 39 | 40 | test('yielding an array of generator functions', testArray( 41 | function* resolving(c) { return yield [function* (){return yield resolvingGenertor(c[0])}, function* (){return yield resolvingGenertor(c[1])}]; }, 42 | function* rejecting(c) { return yield [function* (){return yield rejectingGenertor(c[0])}, function* (){return yield resolvingGenertor(c[1])}]; })); 43 | 44 | test('returning an array of values', testArray( 45 | function* resolving(c) { yield; return c; }, 46 | function* rejecting(c) { yield; throw c[0]; })); 47 | -------------------------------------------------------------------------------- /test/inarrays.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const test = require('tape'); 4 | 5 | const few = require('../index'); 6 | 7 | function testArrayInArray(resolving, rejecting) { 8 | return function (t) { 9 | const expected = [Symbol(), [Symbol()]]; 10 | t.plan(2); 11 | few(resolving(expected), (err, actual) => t.same(actual, expected)); 12 | few(rejecting(expected), (actual) => t.same(actual, expected[0])); 13 | }; 14 | } 15 | 16 | test('yielding an array of promises', testArrayInArray( 17 | function* resolving(c) { return yield [Promise.resolve(c[0]), [Promise.resolve(c[1][0])]]; }, 18 | function* rejecting(c) { yield [[Promise.reject(c[0])], Promise.resolve(c[1])]; })); 19 | 20 | const resolvingFunction = v => cb => process.nextTick(() => cb(null, v)); 21 | const rejectingFunction = v => cb => process.nextTick(() => cb(v)); 22 | test('yielding an array of functions', testArrayInArray( 23 | function* resolving(c) { return yield [resolvingFunction(c[0]), [resolvingFunction(c[1][0])]]; }, 24 | function* rejecting(c) { yield [[rejectingFunction(c[0])], resolvingFunction(c[1])]; })); 25 | 26 | test('yielding an array of values', testArrayInArray( 27 | function* resolving(c) { return yield c; }, 28 | function* rejecting(c) { throw yield c[0]; })); 29 | 30 | test('returning an array of values', testArrayInArray( 31 | function* resolving(c) { yield; return c; }, 32 | function* rejecting(c) { yield; throw c[0]; })); 33 | 34 | function* resolvingGenertor(v) { 35 | return yield resolvingFunction(v); 36 | } 37 | function* rejectingGenertor(v) { 38 | return yield rejectingFunction(v); 39 | } 40 | test('yielding an array of generators', testArrayInArray( 41 | function* resolving(c) { return yield [resolvingGenertor(c[0]), [resolvingGenertor(c[1][0])]]; }, 42 | function* rejecting(c) { return yield [[rejectingGenertor(c[0])], [resolvingFunction(c[1][0])]]; })); 43 | 44 | test('yielding an array of generator functions', testArrayInArray( 45 | function* resolving(c) { return yield [function* () {return yield resolvingGenertor(c[0])}, [function* () {return yield resolvingGenertor(c[1][0])}]]; }, 46 | function* rejecting(c) { return yield [[function* () {return yield rejectingGenertor(c[0])}], function* () {return yield resolvingFunction(c[1][0])}]; })); 47 | -------------------------------------------------------------------------------- /test/inobjects.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const test = require('tape'); 4 | 5 | const few = require('../index'); 6 | 7 | function testObject(resolving, rejecting) { 8 | return function (t) { 9 | const expected = {a: Symbol(), b: {c: Symbol()}}; 10 | t.plan(2); 11 | few(resolving(expected), (err, actual) => t.same(actual, expected)); 12 | few(rejecting(expected), (actual) => t.same(actual, expected.a)); 13 | }; 14 | } 15 | 16 | test('yielding an object of promises', testObject( 17 | function* resolving(o) { return yield {a: Promise.resolve(o.a), b: {c: Promise.resolve(o.b.c)}}; }, 18 | function* rejecting(o) { yield {a: Promise.reject(o.a), b: {c: Promise.resolve(o.b.c)}}; })); 19 | 20 | const resolvingFunction = v => cb => process.nextTick(() => cb(null, v)); 21 | const rejectingFunction = v => cb => process.nextTick(() => cb(v)); 22 | 23 | test('yielding an object of functions', testObject( 24 | function* resolving(o) { return yield {a: resolvingFunction(o.a), b: {c: resolvingFunction(o.b.c)}}; }, 25 | function* rejecting(o) { yield {a: rejectingFunction(o.a), b: {c: resolvingFunction(o.b.c)}}; })); 26 | 27 | test('yielding an object of values', testObject( 28 | function* resolving(o) { return yield o; }, 29 | function* rejecting(o) { throw yield o.a; })); 30 | 31 | function* resolvingGenertor(v) { 32 | return yield resolvingFunction(v); 33 | } 34 | function* rejectingGenertor(v) { 35 | return yield rejectingFunction(v); 36 | } 37 | test('yielding an object of generators', testObject( 38 | function* resolving(o) { return yield {a: resolvingGenertor(o.a), b: {c: resolvingGenertor(o.b.c)}}; }, 39 | function* rejecting(o) { yield {a: rejectingGenertor(o.a), b: {c: resolvingGenertor(o.b.c)}}; })); 40 | 41 | test('yielding an object of generator functions', testObject( 42 | function* resolving(o) { return yield {a: function* () {return yield resolvingGenertor(o.a)}, b: {c: function* () {return yield resolvingGenertor(o.b.c)}}}; }, 43 | function* rejecting(o) { return yield {a: function* () {return yield rejectingGenertor(o.a)}, b: {c: function* () {return yield resolvingGenertor(o.b.c)}}}; })); 44 | 45 | test('returning an object of values', testObject( 46 | function* resolving(o) { yield; return o; }, 47 | function* rejecting(o) { yield; throw o.a; })); 48 | -------------------------------------------------------------------------------- /test/objects.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const test = require('tape'); 4 | 5 | const few = require('../index'); 6 | 7 | function testObject(resolving, rejecting) { 8 | return function (t) { 9 | const expected = {a: Symbol(), b: Symbol()}; 10 | t.plan(2); 11 | few(resolving(expected), (err, actual) => t.same(actual, expected)); 12 | few(rejecting(expected), (actual) => t.same(actual, expected.a)); 13 | }; 14 | } 15 | 16 | test('yielding an object of promises', testObject( 17 | function* resolving(o) { return yield {a: Promise.resolve(o.a), b: Promise.resolve(o.b)}; }, 18 | function* rejecting(o) { yield {a: Promise.reject(o.a), b: Promise.resolve(o.b)}; })); 19 | 20 | test('yielding an object of generator functions', testObject( 21 | function* resolving(o) { return yield {a: function* () {return o.a}, b: function* () {return o.b}}; }, 22 | function* rejecting(o) { return yield {a: function* () {throw o.a}, b: function* () {throw o.b}}; })); 23 | 24 | const resolvingFunction = v => cb => process.nextTick(() => cb(null, v)); 25 | const rejectingFunction = v => cb => process.nextTick(() => cb(v)); 26 | 27 | test('yielding an object of functions', testObject( 28 | function* resolving(o) { return yield {a: resolvingFunction(o.a), b: resolvingFunction(o.b)}; }, 29 | function* rejecting(o) { yield {a: rejectingFunction(o.a), b: resolvingFunction(o.b)}; })); 30 | 31 | test('yielding an object of values', testObject( 32 | function* resolving(o) { return yield o; }, 33 | function* rejecting(o) { throw yield o.a; })); 34 | 35 | function* resolvingGenertor(v) { 36 | return yield resolvingFunction(v); 37 | } 38 | function* rejectingGenertor(v) { 39 | return yield rejectingFunction(v); 40 | } 41 | test('yielding an object of generators', testObject( 42 | function* resolving(o) { return yield {a: resolvingGenertor(o.a), b: resolvingGenertor(o.b)}; }, 43 | function* rejecting(o) { yield {a: rejectingGenertor(o.a), b: resolvingGenertor(o.b)}; })); 44 | 45 | test('returning an object of values', testObject( 46 | function* resolving(o) { yield; return o; }, 47 | function* rejecting(o) { yield; throw o.a; })); 48 | 49 | test('object keys preserve order', function (t) { 50 | t.plan(1); 51 | few(function* () { 52 | return yield {a: cb => process.nextTick(() => cb(null, 1)), b: cb => cb(null, 2)}; 53 | }, (err, actual) => t.same(Object.keys(actual), ['a', 'b'])); 54 | }); 55 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function isFunction(v) { 4 | return typeof v === 'function'; 5 | } 6 | 7 | function isThenable(v) { 8 | return typeof v === 'object' && typeof v.then === 'function'; 9 | } 10 | 11 | function isGeneratorFunction(v) { 12 | return isFunction(v) && v.constructor.name === 'GeneratorFunction'; 13 | } 14 | 15 | function isObject(o) { 16 | return o instanceof Object; 17 | } 18 | 19 | function isGenerator(v) { 20 | return isObject(v) && isFunction(v.next) && isFunction(v.throw); 21 | } 22 | 23 | function thenableToFunction(t) { 24 | return cb => t.then(v => cb(null, v), err => cb(err)); 25 | } 26 | 27 | function generatorToFunction(gen) { 28 | return cb => advance(gen, cb); 29 | } 30 | 31 | function valueToFunction(v) { 32 | return isGeneratorFunction(v) ? generatorToFunction(v()) : 33 | isFunction(v) ? v : 34 | isGenerator(v) ? generatorToFunction(v) : 35 | isThenable(v) ? thenableToFunction(v) : 36 | Array.isArray(v) ? arrayToFunction(v) : 37 | isObject(v) ? objectToFunction(v) : 38 | cb => process.nextTick(() => cb(null, v)); 39 | } 40 | 41 | function arrayToFunction(arr) { 42 | return iterableToFunction( 43 | () => new Array(arr.length), 44 | cb => arr.forEach(cb), 45 | count => count === arr.length); 46 | } 47 | 48 | 49 | function objectToFunction(o) { 50 | const keys = Object.keys(o); 51 | return iterableToFunction( 52 | () => Object.assign({}, o), 53 | cb => keys.forEach(k => cb(o[k], k)), 54 | count => count === keys.length); 55 | } 56 | 57 | function iterableToFunction(createDest, iterate, hasFinished) { 58 | return function (cb) { 59 | const dest = createDest(); 60 | let count = 0; 61 | let stopIteration = false; 62 | iterate(function (e, i) { 63 | valueToFunction(e)(function (err, value) { 64 | if (stopIteration) { 65 | return; 66 | } 67 | dest[i] = value; 68 | count += 1; 69 | if (err || hasFinished(count)) { 70 | cb(err, dest); 71 | stopIteration = true; 72 | } 73 | }); 74 | }); 75 | }; 76 | } 77 | 78 | function advance(gen, cb, err, result) { 79 | try { 80 | const r = err ? gen.throw(err) : gen.next(result); 81 | return r.done ? cb(null, r.value) : 82 | valueToFunction(r.value)((fnErr, fnResult) => advance(gen, cb, fnErr, fnResult)); 83 | } catch (genErr) { 84 | return cb(genErr); 85 | } 86 | } 87 | 88 | class ErrorGenerator { 89 | next() { 90 | throw new TypeError('genOrFn must be a generator or a generator function'); 91 | } 92 | } 93 | 94 | function few(genOrFn, cb) { 95 | advance( 96 | isGenerator(genOrFn) ? genOrFn : 97 | isGeneratorFunction(genOrFn) ? genOrFn() : 98 | new ErrorGenerator(), 99 | isFunction(cb) ? cb : err => { if (err) process.nextTick(() => { throw err; }); }); 100 | } 101 | 102 | module.exports = few; 103 | -------------------------------------------------------------------------------- /test/multiple.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const test = require('tape'); 4 | 5 | const few = require('../index'); 6 | 7 | function testMultipleValues(resolving, rejecting) { 8 | return function (t) { 9 | const first = 5; 10 | const second = 10; 11 | t.plan(2); 12 | few(resolving(first, second), (err, actual) => t.is(actual, first * second)); 13 | few(rejecting(first, second), (actual) => t.is(actual, first * second)); 14 | }; 15 | } 16 | 17 | test('yielding multiple promises', testMultipleValues( 18 | function* resolving(a, b) { return (yield Promise.resolve(a)) * (yield Promise.resolve(b)); }, 19 | function* rejecting(a, b) { return (yield Promise.reject(a * (yield Promise.resolve(b)))); })); 20 | 21 | test('yielding multiple generator functions', testMultipleValues( 22 | function* resolving(a, b) { return (yield function* () {return a}) * (yield function* () {return b}); }, 23 | function* rejecting(a, b) { return (yield function* () {throw (a * (yield function* () {return b}));})})); 24 | 25 | test('yielding multiple initiated generator functions', testMultipleValues( 26 | function* resolving(a, b) { return (yield function* () {return a}()) * (yield function* () {return b}()); }, 27 | function* rejecting(a, b) { return (yield function* () {throw (a * (yield function* () {return b}()));}())})); 28 | 29 | const resolvingFunction = v => cb => process.nextTick(() => cb(null, v)); 30 | const rejectingFunction = v => cb => process.nextTick(() => cb(v)); 31 | test('yielding multiple functions', testMultipleValues( 32 | function* resolving(a, b) { return (yield resolvingFunction(a)) * (yield resolvingFunction(b)); }, 33 | function* rejecting(a, b) { return (yield rejectingFunction(a * (yield resolvingFunction(b)))); })); 34 | 35 | const resolvingSynchronousFunction = v => cb => cb(null, v); 36 | const rejectingSynchronousFunction = v => cb => cb(v); 37 | test('yielding multiple functions', testMultipleValues( 38 | function* resolving(a, b) { return (yield resolvingSynchronousFunction(a)) * (yield resolvingSynchronousFunction(b)); }, 39 | function* rejecting(a, b) { return (yield rejectingSynchronousFunction(a * (yield resolvingSynchronousFunction(b)))); })); 40 | 41 | test('yielding multiple values', testMultipleValues( 42 | function* resolving(a, b) { return (yield a) * (yield b); }, 43 | function* rejecting(a, b) { throw (yield a) * (yield b); })); 44 | 45 | test('returning multiple values', testMultipleValues( 46 | function* resolving(a, b) { yield; return a * b; }, 47 | function* rejecting(a, b) { yield; throw a * b; })); 48 | 49 | test('yielding a promise and a function', testMultipleValues( 50 | function* resolving(a, b) { return (yield Promise.resolve(a)) * (yield resolvingFunction(b)); }, 51 | function* rejecting(a, b) { return (yield rejectingFunction(a * (yield Promise.resolve(b)))); })); 52 | 53 | test('yielding a value and a function', testMultipleValues( 54 | function* resolving(a, b) { return (yield a) * (yield resolvingFunction(b)); }, 55 | function* rejecting(a, b) { return (yield rejectingFunction(a * (yield b))); })); 56 | -------------------------------------------------------------------------------- /dist/index.min.js: -------------------------------------------------------------------------------- 1 | !function(n){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=n();else if("function"==typeof define&&define.amd)define([],n);else{var t;t="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,t.few=n()}}(function(){return function n(t,e,r){function o(i,f){if(!e[i]){if(!t[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var s=e[i]={exports:{}};t[i][0].call(s.exports,function(n){var e=t[i][1][n];return o(e?e:n)},s,s.exports,n,t,e,r)}return e[i].exports}for(var u="function"==typeof require&&require,i=0;i1)for(var e=1;e callback(null, v)); 24 | } 25 | 26 | function* generateValue(v) { 27 | return yield cb => returnValue(v, cb); 28 | } 29 | 30 | // Multiple invocations of few run asynchronously 31 | 32 | few(function* () { 33 | // Yield or delegate directly 34 | const a = yield cb => returnValue(1, cb); 35 | const b = yield Promise.resolve(2); 36 | const c = yield 3; 37 | const d = yield* generateValue(4); // yield generateValue(4); Also works 38 | 39 | // Prints 1 2 3 4 40 | console.log(a, b, c, d); 41 | }); 42 | 43 | few(function* () { 44 | // Parallelize using arrays 45 | const arr = yield [ 46 | cb => returnValue(1, cb), 47 | Promise.resolve(2), 48 | 3, 49 | generateValue(4) 50 | ]; 51 | 52 | // Prints [ 1, 2, 3, 4 ] 53 | console.log(arr); 54 | }); 55 | 56 | few(function* () { 57 | // Parallelize using objects 58 | const obj = yield { 59 | a: cb => returnValue(1, cb), 60 | b: Promise.resolve(2), 61 | c: 3, 62 | d: generateValue(4) 63 | }; 64 | 65 | // Prints { a: 1, b: 2, c: 3, d: 4 } 66 | console.log(obj); 67 | }); 68 | ``` 69 | ## Usage 70 | ### few(genOrFn[, callback]) 71 | `genOrFn` must be an initialized generator or a generator function that does not expect any arguments. Any other type will produce a `TypeError`. 72 | `callback`, if provided, must be a node-style callback, i.e. accepting an error and a result as arguments. 73 | The return value of the generator will be provided as the result argument and if an error is thrown, it will be provided as the error argument. 74 | If `callback` is not provided, any error that the generator produces, will be thrown. 75 | 76 | ### Yieldable Objects 77 | few supports the following types to be yielded: 78 | - Single node-style callback argument functions (aka thunks) 79 | - Promises 80 | - Simple values, which will be returned as-is 81 | - Arrays combining thunks, promises, generators or simple values to be run in parallel 82 | - Objects containing thunks, promises, generators or simple values to be run in parallel 83 | 84 | ### Parallelization 85 | few allows parallelization by yielding an array or an object. 86 | The yielded object or array may contain any combination of: 87 | - Single node-style callback argument functions (aka thunks) 88 | - Promises 89 | - Initialized generators 90 | - Simple values, which will be returned as-is 91 | 92 | When all given elements have finished processing, a new object or array that contains the results of the given elements in the same order will be returned. 93 | If any of the elements provides an error, the error will be thrown inside the generator. 94 | 95 | ### Generator Delegation Support 96 | Delegation is supported using the `yield*` expression. 97 | To run in parallel, a generator can be passed as an element of the yielded array. 98 | 99 | ### Error Handling 100 | Any error originating from yielded objects will be thrown inside the generator, and can be caught using `try...catch`. 101 | For example, the following code prints ERROR to stderr: 102 | ```javascript 103 | few(function* () { 104 | try { 105 | yield Promise.reject(new Error('ERROR')); 106 | } catch (err) { 107 | console.error(err.message); 108 | } 109 | }); 110 | ``` 111 | If an error is thrown inside a generator (and not caught), it will be passed to the callback given as a second argument to `few` or thrown if a callback has not been given. 112 | The following example also prints ERROR to stderr: 113 | ```javascript 114 | few(function* () { 115 | yield Promise.reject(new Error('ERROR')); 116 | }, (err, result) => { console.error(err.message); }); 117 | ``` 118 | In the following example, the uncaught error will crash the process. Make sure you handle all errors! 119 | ```javascript 120 | few(function* () { 121 | yield Promise.reject(new Error('ERROR')); 122 | }); 123 | ``` 124 | 125 | ## License 126 | Licensed under Apache 2.0 127 | -------------------------------------------------------------------------------- /dist/index.js: -------------------------------------------------------------------------------- 1 | (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.few = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 1) { 184 | for (var i = 1; i < arguments.length; i++) { 185 | args[i - 1] = arguments[i]; 186 | } 187 | } 188 | queue.push(new Item(fun, args)); 189 | if (queue.length === 1 && !draining) { 190 | setTimeout(drainQueue, 0); 191 | } 192 | }; 193 | 194 | // v8 likes predictible objects 195 | function Item(fun, array) { 196 | this.fun = fun; 197 | this.array = array; 198 | } 199 | Item.prototype.run = function () { 200 | this.fun.apply(null, this.array); 201 | }; 202 | process.title = 'browser'; 203 | process.browser = true; 204 | process.env = {}; 205 | process.argv = []; 206 | process.version = ''; // empty string to avoid regexp issues 207 | process.versions = {}; 208 | 209 | function noop() {} 210 | 211 | process.on = noop; 212 | process.addListener = noop; 213 | process.once = noop; 214 | process.off = noop; 215 | process.removeListener = noop; 216 | process.removeAllListeners = noop; 217 | process.emit = noop; 218 | 219 | process.binding = function (name) { 220 | throw new Error('process.binding is not supported'); 221 | }; 222 | 223 | process.cwd = function () { return '/' }; 224 | process.chdir = function (dir) { 225 | throw new Error('process.chdir is not supported'); 226 | }; 227 | process.umask = function() { return 0; }; 228 | 229 | },{}]},{},[1])(1) 230 | }); 231 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJkaXN0L2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3Byb2Nlc3MvYnJvd3Nlci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDbElBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKFwidmFsdWVcIiBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSgpO1xuXG52YXIgX3R5cGVvZiA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgU3ltYm9sLml0ZXJhdG9yID09PSBcInN5bWJvbFwiID8gZnVuY3Rpb24gKG9iaikgeyByZXR1cm4gdHlwZW9mIG9iajsgfSA6IGZ1bmN0aW9uIChvYmopIHsgcmV0dXJuIG9iaiAmJiB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb2JqLmNvbnN0cnVjdG9yID09PSBTeW1ib2wgPyBcInN5bWJvbFwiIDogdHlwZW9mIG9iajsgfTtcblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpOyB9IH1cblxuZnVuY3Rpb24gaXNGdW5jdGlvbih2KSB7XG4gIHJldHVybiB0eXBlb2YgdiA9PT0gJ2Z1bmN0aW9uJztcbn1cblxuZnVuY3Rpb24gaXNUaGVuYWJsZSh2KSB7XG4gIHJldHVybiAodHlwZW9mIHYgPT09ICd1bmRlZmluZWQnID8gJ3VuZGVmaW5lZCcgOiBfdHlwZW9mKHYpKSA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIHYudGhlbiA9PT0gJ2Z1bmN0aW9uJztcbn1cblxuZnVuY3Rpb24gaXNHZW5lcmF0b3JGdW5jdGlvbih2KSB7XG4gIHJldHVybiBpc0Z1bmN0aW9uKHYpICYmIHYuY29uc3RydWN0b3IubmFtZSA9PT0gJ0dlbmVyYXRvckZ1bmN0aW9uJztcbn1cblxuZnVuY3Rpb24gaXNPYmplY3Qobykge1xuICByZXR1cm4gbyBpbnN0YW5jZW9mIE9iamVjdDtcbn1cblxuZnVuY3Rpb24gaXNHZW5lcmF0b3Iodikge1xuICByZXR1cm4gaXNPYmplY3QodikgJiYgaXNGdW5jdGlvbih2Lm5leHQpICYmIGlzRnVuY3Rpb24odi50aHJvdyk7XG59XG5cbmZ1bmN0aW9uIHRoZW5hYmxlVG9GdW5jdGlvbih0KSB7XG4gIHJldHVybiBmdW5jdGlvbiAoY2IpIHtcbiAgICByZXR1cm4gdC50aGVuKGZ1bmN0aW9uICh2KSB7XG4gICAgICByZXR1cm4gY2IobnVsbCwgdik7XG4gICAgfSwgZnVuY3Rpb24gKGVycikge1xuICAgICAgcmV0dXJuIGNiKGVycik7XG4gICAgfSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGdlbmVyYXRvclRvRnVuY3Rpb24oZ2VuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoY2IpIHtcbiAgICByZXR1cm4gYWR2YW5jZShnZW4sIGNiKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gdmFsdWVUb0Z1bmN0aW9uKHYpIHtcbiAgcmV0dXJuIGlzR2VuZXJhdG9yRnVuY3Rpb24odikgPyBnZW5lcmF0b3JUb0Z1bmN0aW9uKHYoKSkgOiBpc0dlbmVyYXRvcih2KSA/IGdlbmVyYXRvclRvRnVuY3Rpb24odikgOiBpc0Z1bmN0aW9uKHYpID8gdiA6IGlzVGhlbmFibGUodikgPyB0aGVuYWJsZVRvRnVuY3Rpb24odikgOiBBcnJheS5pc0FycmF5KHYpID8gYXJyYXlUb0Z1bmN0aW9uKHYpIDogaXNPYmplY3QodikgPyBvYmplY3RUb0Z1bmN0aW9uKHYpIDogZnVuY3Rpb24gKGNiKSB7XG4gICAgcmV0dXJuIHByb2Nlc3MubmV4dFRpY2soZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIGNiKG51bGwsIHYpO1xuICAgIH0pO1xuICB9O1xufVxuXG5mdW5jdGlvbiBhcnJheVRvRnVuY3Rpb24oYXJyKSB7XG4gIHJldHVybiBpdGVyYWJsZVRvRnVuY3Rpb24oZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBuZXcgQXJyYXkoYXJyLmxlbmd0aCk7XG4gIH0sIGZ1bmN0aW9uIChjYikge1xuICAgIHJldHVybiBhcnIuZm9yRWFjaChjYik7XG4gIH0sIGZ1bmN0aW9uIChjb3VudCkge1xuICAgIHJldHVybiBjb3VudCA9PT0gYXJyLmxlbmd0aDtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIG9iamVjdFRvRnVuY3Rpb24obykge1xuICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKG8pO1xuICByZXR1cm4gaXRlcmFibGVUb0Z1bmN0aW9uKGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gT2JqZWN0LmFzc2lnbih7fSwgbyk7XG4gIH0sIGZ1bmN0aW9uIChjYikge1xuICAgIHJldHVybiBrZXlzLmZvckVhY2goZnVuY3Rpb24gKGspIHtcbiAgICAgIHJldHVybiBjYihvW2tdLCBrKTtcbiAgICB9KTtcbiAgfSwgZnVuY3Rpb24gKGNvdW50KSB7XG4gICAgcmV0dXJuIGNvdW50ID09PSBrZXlzLmxlbmd0aDtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGl0ZXJhYmxlVG9GdW5jdGlvbihjcmVhdGVEZXN0LCBpdGVyYXRlLCBoYXNGaW5pc2hlZCkge1xuICByZXR1cm4gZnVuY3Rpb24gKGNiKSB7XG4gICAgdmFyIGRlc3QgPSBjcmVhdGVEZXN0KCk7XG4gICAgdmFyIGNvdW50ID0gMDtcbiAgICB2YXIgc3RvcEl0ZXJhdGlvbiA9IGZhbHNlO1xuICAgIGl0ZXJhdGUoZnVuY3Rpb24gKGUsIGkpIHtcbiAgICAgIHZhbHVlVG9GdW5jdGlvbihlKShmdW5jdGlvbiAoZXJyLCB2YWx1ZSkge1xuICAgICAgICBpZiAoc3RvcEl0ZXJhdGlvbikge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBkZXN0W2ldID0gdmFsdWU7XG4gICAgICAgIGNvdW50ICs9IDE7XG4gICAgICAgIGlmIChlcnIgfHwgaGFzRmluaXNoZWQoY291bnQpKSB7XG4gICAgICAgICAgY2IoZXJyLCBkZXN0KTtcbiAgICAgICAgICBzdG9wSXRlcmF0aW9uID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGFkdmFuY2UoZ2VuLCBjYiwgZXJyLCByZXN1bHQpIHtcbiAgdHJ5IHtcbiAgICB2YXIgciA9IGVyciA/IGdlbi50aHJvdyhlcnIpIDogZ2VuLm5leHQocmVzdWx0KTtcbiAgICByZXR1cm4gci5kb25lID8gY2IobnVsbCwgci52YWx1ZSkgOiB2YWx1ZVRvRnVuY3Rpb24oci52YWx1ZSkoZnVuY3Rpb24gKGZuRXJyLCBmblJlc3VsdCkge1xuICAgICAgcmV0dXJuIGFkdmFuY2UoZ2VuLCBjYiwgZm5FcnIsIGZuUmVzdWx0KTtcbiAgICB9KTtcbiAgfSBjYXRjaCAoZ2VuRXJyKSB7XG4gICAgcmV0dXJuIGNiKGdlbkVycik7XG4gIH1cbn1cblxudmFyIEVycm9yR2VuZXJhdG9yID0gZnVuY3Rpb24gKCkge1xuICBmdW5jdGlvbiBFcnJvckdlbmVyYXRvcigpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgRXJyb3JHZW5lcmF0b3IpO1xuICB9XG5cbiAgX2NyZWF0ZUNsYXNzKEVycm9yR2VuZXJhdG9yLCBbe1xuICAgIGtleTogJ25leHQnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBuZXh0KCkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZ2VuT3JGbiBtdXN0IGJlIGEgZ2VuZXJhdG9yIG9yIGEgZ2VuZXJhdG9yIGZ1bmN0aW9uJyk7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIEVycm9yR2VuZXJhdG9yO1xufSgpO1xuXG5mdW5jdGlvbiBmZXcoZ2VuT3JGbiwgY2IpIHtcbiAgYWR2YW5jZShpc0dlbmVyYXRvcihnZW5PckZuKSA/IGdlbk9yRm4gOiBpc0dlbmVyYXRvckZ1bmN0aW9uKGdlbk9yRm4pID8gZ2VuT3JGbigpIDogbmV3IEVycm9yR2VuZXJhdG9yKCksIGlzRnVuY3Rpb24oY2IpID8gY2IgOiBmdW5jdGlvbiAoZXJyKSB7XG4gICAgaWYgKGVycikgcHJvY2Vzcy5uZXh0VGljayhmdW5jdGlvbiAoKSB7XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfSk7XG4gIH0pO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGZldzsiLCIvLyBzaGltIGZvciB1c2luZyBwcm9jZXNzIGluIGJyb3dzZXJcblxudmFyIHByb2Nlc3MgPSBtb2R1bGUuZXhwb3J0cyA9IHt9O1xudmFyIHF1ZXVlID0gW107XG52YXIgZHJhaW5pbmcgPSBmYWxzZTtcbnZhciBjdXJyZW50UXVldWU7XG52YXIgcXVldWVJbmRleCA9IC0xO1xuXG5mdW5jdGlvbiBjbGVhblVwTmV4dFRpY2soKSB7XG4gICAgZHJhaW5pbmcgPSBmYWxzZTtcbiAgICBpZiAoY3VycmVudFF1ZXVlLmxlbmd0aCkge1xuICAgICAgICBxdWV1ZSA9IGN1cnJlbnRRdWV1ZS5jb25jYXQocXVldWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHF1ZXVlSW5kZXggPSAtMTtcbiAgICB9XG4gICAgaWYgKHF1ZXVlLmxlbmd0aCkge1xuICAgICAgICBkcmFpblF1ZXVlKCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBkcmFpblF1ZXVlKCkge1xuICAgIGlmIChkcmFpbmluZykge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciB0aW1lb3V0ID0gc2V0VGltZW91dChjbGVhblVwTmV4dFRpY2spO1xuICAgIGRyYWluaW5nID0gdHJ1ZTtcblxuICAgIHZhciBsZW4gPSBxdWV1ZS5sZW5ndGg7XG4gICAgd2hpbGUobGVuKSB7XG4gICAgICAgIGN1cnJlbnRRdWV1ZSA9IHF1ZXVlO1xuICAgICAgICBxdWV1ZSA9IFtdO1xuICAgICAgICB3aGlsZSAoKytxdWV1ZUluZGV4IDwgbGVuKSB7XG4gICAgICAgICAgICBpZiAoY3VycmVudFF1ZXVlKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudFF1ZXVlW3F1ZXVlSW5kZXhdLnJ1bigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHF1ZXVlSW5kZXggPSAtMTtcbiAgICAgICAgbGVuID0gcXVldWUubGVuZ3RoO1xuICAgIH1cbiAgICBjdXJyZW50UXVldWUgPSBudWxsO1xuICAgIGRyYWluaW5nID0gZmFsc2U7XG4gICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xufVxuXG5wcm9jZXNzLm5leHRUaWNrID0gZnVuY3Rpb24gKGZ1bikge1xuICAgIHZhciBhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGggLSAxKTtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuICAgICAgICB9XG4gICAgfVxuICAgIHF1ZXVlLnB1c2gobmV3IEl0ZW0oZnVuLCBhcmdzKSk7XG4gICAgaWYgKHF1ZXVlLmxlbmd0aCA9PT0gMSAmJiAhZHJhaW5pbmcpIHtcbiAgICAgICAgc2V0VGltZW91dChkcmFpblF1ZXVlLCAwKTtcbiAgICB9XG59O1xuXG4vLyB2OCBsaWtlcyBwcmVkaWN0aWJsZSBvYmplY3RzXG5mdW5jdGlvbiBJdGVtKGZ1biwgYXJyYXkpIHtcbiAgICB0aGlzLmZ1biA9IGZ1bjtcbiAgICB0aGlzLmFycmF5ID0gYXJyYXk7XG59XG5JdGVtLnByb3RvdHlwZS5ydW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5mdW4uYXBwbHkobnVsbCwgdGhpcy5hcnJheSk7XG59O1xucHJvY2Vzcy50aXRsZSA9ICdicm93c2VyJztcbnByb2Nlc3MuYnJvd3NlciA9IHRydWU7XG5wcm9jZXNzLmVudiA9IHt9O1xucHJvY2Vzcy5hcmd2ID0gW107XG5wcm9jZXNzLnZlcnNpb24gPSAnJzsgLy8gZW1wdHkgc3RyaW5nIHRvIGF2b2lkIHJlZ2V4cCBpc3N1ZXNcbnByb2Nlc3MudmVyc2lvbnMgPSB7fTtcblxuZnVuY3Rpb24gbm9vcCgpIHt9XG5cbnByb2Nlc3Mub24gPSBub29wO1xucHJvY2Vzcy5hZGRMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLm9uY2UgPSBub29wO1xucHJvY2Vzcy5vZmYgPSBub29wO1xucHJvY2Vzcy5yZW1vdmVMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUFsbExpc3RlbmVycyA9IG5vb3A7XG5wcm9jZXNzLmVtaXQgPSBub29wO1xuXG5wcm9jZXNzLmJpbmRpbmcgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5iaW5kaW5nIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG5cbnByb2Nlc3MuY3dkID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gJy8nIH07XG5wcm9jZXNzLmNoZGlyID0gZnVuY3Rpb24gKGRpcikge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5jaGRpciBpcyBub3Qgc3VwcG9ydGVkJyk7XG59O1xucHJvY2Vzcy51bWFzayA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gMDsgfTtcbiJdfQ== 232 | -------------------------------------------------------------------------------- /dist/maps/index.min.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["index.js"],"names":["f","exports","module","define","amd","g","window","global","self","this","few","e","t","n","r","s","o","u","a","require","i","Error","code","l","call","length",1,"process","_classCallCheck","instance","Constructor","TypeError","isFunction","v","isThenable","_typeof","then","isGeneratorFunction","constructor","name","isObject","Object","isGenerator","next","thenableToFunction","cb","err","generatorToFunction","gen","advance","valueToFunction","Array","isArray","arrayToFunction","objectToFunction","nextTick","arr","iterableToFunction","forEach","count","keys","assign","k","createDest","iterate","hasFinished","dest","stopIteration","value","result","done","fnErr","fnResult","genErr","genOrFn","ErrorGenerator","_createClass","defineProperties","target","props","descriptor","enumerable","configurable","writable","defineProperty","key","protoProps","staticProps","prototype","Symbol","iterator","obj","_process",2,"cleanUpNextTick","draining","currentQueue","queue","concat","queueIndex","drainQueue","timeout","setTimeout","len","run","clearTimeout","Item","fun","array","noop","args","arguments","push","apply","title","browser","env","argv","version","versions","on","addListener","once","off","removeListener","removeAllListeners","emit","binding","cwd","chdir","dir","umask"],"mappings":"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","file":"index.min.js","sourcesContent":["(function(f){if(typeof exports===\"object\"&&typeof module!==\"undefined\"){module.exports=f()}else if(typeof define===\"function\"&&define.amd){define([],f)}else{var g;if(typeof window!==\"undefined\"){g=window}else if(typeof global!==\"undefined\"){g=global}else if(typeof self!==\"undefined\"){g=self}else{g=this}g.few = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o 1) {\n for (var i = 1; i < arguments.length; i++) {\n args[i - 1] = arguments[i];\n }\n }\n queue.push(new Item(fun, args));\n if (queue.length === 1 && !draining) {\n setTimeout(drainQueue, 0);\n }\n};\n\n// v8 likes predictible objects\nfunction Item(fun, array) {\n this.fun = fun;\n this.array = array;\n}\nItem.prototype.run = function () {\n this.fun.apply(null, this.array);\n};\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n throw new Error('process.binding is not supported');\n};\n\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}]},{},[1])(1)\n});\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJkaXN0L2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3Byb2Nlc3MvYnJvd3Nlci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDbElBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKFwidmFsdWVcIiBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSgpO1xuXG52YXIgX3R5cGVvZiA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgU3ltYm9sLml0ZXJhdG9yID09PSBcInN5bWJvbFwiID8gZnVuY3Rpb24gKG9iaikgeyByZXR1cm4gdHlwZW9mIG9iajsgfSA6IGZ1bmN0aW9uIChvYmopIHsgcmV0dXJuIG9iaiAmJiB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb2JqLmNvbnN0cnVjdG9yID09PSBTeW1ib2wgPyBcInN5bWJvbFwiIDogdHlwZW9mIG9iajsgfTtcblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpOyB9IH1cblxuZnVuY3Rpb24gaXNGdW5jdGlvbih2KSB7XG4gIHJldHVybiB0eXBlb2YgdiA9PT0gJ2Z1bmN0aW9uJztcbn1cblxuZnVuY3Rpb24gaXNUaGVuYWJsZSh2KSB7XG4gIHJldHVybiAodHlwZW9mIHYgPT09ICd1bmRlZmluZWQnID8gJ3VuZGVmaW5lZCcgOiBfdHlwZW9mKHYpKSA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIHYudGhlbiA9PT0gJ2Z1bmN0aW9uJztcbn1cblxuZnVuY3Rpb24gaXNHZW5lcmF0b3JGdW5jdGlvbih2KSB7XG4gIHJldHVybiBpc0Z1bmN0aW9uKHYpICYmIHYuY29uc3RydWN0b3IubmFtZSA9PT0gJ0dlbmVyYXRvckZ1bmN0aW9uJztcbn1cblxuZnVuY3Rpb24gaXNPYmplY3Qobykge1xuICByZXR1cm4gbyBpbnN0YW5jZW9mIE9iamVjdDtcbn1cblxuZnVuY3Rpb24gaXNHZW5lcmF0b3Iodikge1xuICByZXR1cm4gaXNPYmplY3QodikgJiYgaXNGdW5jdGlvbih2Lm5leHQpICYmIGlzRnVuY3Rpb24odi50aHJvdyk7XG59XG5cbmZ1bmN0aW9uIHRoZW5hYmxlVG9GdW5jdGlvbih0KSB7XG4gIHJldHVybiBmdW5jdGlvbiAoY2IpIHtcbiAgICByZXR1cm4gdC50aGVuKGZ1bmN0aW9uICh2KSB7XG4gICAgICByZXR1cm4gY2IobnVsbCwgdik7XG4gICAgfSwgZnVuY3Rpb24gKGVycikge1xuICAgICAgcmV0dXJuIGNiKGVycik7XG4gICAgfSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGdlbmVyYXRvclRvRnVuY3Rpb24oZ2VuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoY2IpIHtcbiAgICByZXR1cm4gYWR2YW5jZShnZW4sIGNiKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gdmFsdWVUb0Z1bmN0aW9uKHYpIHtcbiAgcmV0dXJuIGlzR2VuZXJhdG9yRnVuY3Rpb24odikgPyBnZW5lcmF0b3JUb0Z1bmN0aW9uKHYoKSkgOiBpc0dlbmVyYXRvcih2KSA/IGdlbmVyYXRvclRvRnVuY3Rpb24odikgOiBpc0Z1bmN0aW9uKHYpID8gdiA6IGlzVGhlbmFibGUodikgPyB0aGVuYWJsZVRvRnVuY3Rpb24odikgOiBBcnJheS5pc0FycmF5KHYpID8gYXJyYXlUb0Z1bmN0aW9uKHYpIDogaXNPYmplY3QodikgPyBvYmplY3RUb0Z1bmN0aW9uKHYpIDogZnVuY3Rpb24gKGNiKSB7XG4gICAgcmV0dXJuIHByb2Nlc3MubmV4dFRpY2soZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIGNiKG51bGwsIHYpO1xuICAgIH0pO1xuICB9O1xufVxuXG5mdW5jdGlvbiBhcnJheVRvRnVuY3Rpb24oYXJyKSB7XG4gIHJldHVybiBpdGVyYWJsZVRvRnVuY3Rpb24oZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBuZXcgQXJyYXkoYXJyLmxlbmd0aCk7XG4gIH0sIGZ1bmN0aW9uIChjYikge1xuICAgIHJldHVybiBhcnIuZm9yRWFjaChjYik7XG4gIH0sIGZ1bmN0aW9uIChjb3VudCkge1xuICAgIHJldHVybiBjb3VudCA9PT0gYXJyLmxlbmd0aDtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIG9iamVjdFRvRnVuY3Rpb24obykge1xuICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKG8pO1xuICByZXR1cm4gaXRlcmFibGVUb0Z1bmN0aW9uKGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gT2JqZWN0LmFzc2lnbih7fSwgbyk7XG4gIH0sIGZ1bmN0aW9uIChjYikge1xuICAgIHJldHVybiBrZXlzLmZvckVhY2goZnVuY3Rpb24gKGspIHtcbiAgICAgIHJldHVybiBjYihvW2tdLCBrKTtcbiAgICB9KTtcbiAgfSwgZnVuY3Rpb24gKGNvdW50KSB7XG4gICAgcmV0dXJuIGNvdW50ID09PSBrZXlzLmxlbmd0aDtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGl0ZXJhYmxlVG9GdW5jdGlvbihjcmVhdGVEZXN0LCBpdGVyYXRlLCBoYXNGaW5pc2hlZCkge1xuICByZXR1cm4gZnVuY3Rpb24gKGNiKSB7XG4gICAgdmFyIGRlc3QgPSBjcmVhdGVEZXN0KCk7XG4gICAgdmFyIGNvdW50ID0gMDtcbiAgICB2YXIgc3RvcEl0ZXJhdGlvbiA9IGZhbHNlO1xuICAgIGl0ZXJhdGUoZnVuY3Rpb24gKGUsIGkpIHtcbiAgICAgIHZhbHVlVG9GdW5jdGlvbihlKShmdW5jdGlvbiAoZXJyLCB2YWx1ZSkge1xuICAgICAgICBpZiAoc3RvcEl0ZXJhdGlvbikge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBkZXN0W2ldID0gdmFsdWU7XG4gICAgICAgIGNvdW50ICs9IDE7XG4gICAgICAgIGlmIChlcnIgfHwgaGFzRmluaXNoZWQoY291bnQpKSB7XG4gICAgICAgICAgY2IoZXJyLCBkZXN0KTtcbiAgICAgICAgICBzdG9wSXRlcmF0aW9uID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGFkdmFuY2UoZ2VuLCBjYiwgZXJyLCByZXN1bHQpIHtcbiAgdHJ5IHtcbiAgICB2YXIgciA9IGVyciA/IGdlbi50aHJvdyhlcnIpIDogZ2VuLm5leHQocmVzdWx0KTtcbiAgICByZXR1cm4gci5kb25lID8gY2IobnVsbCwgci52YWx1ZSkgOiB2YWx1ZVRvRnVuY3Rpb24oci52YWx1ZSkoZnVuY3Rpb24gKGZuRXJyLCBmblJlc3VsdCkge1xuICAgICAgcmV0dXJuIGFkdmFuY2UoZ2VuLCBjYiwgZm5FcnIsIGZuUmVzdWx0KTtcbiAgICB9KTtcbiAgfSBjYXRjaCAoZ2VuRXJyKSB7XG4gICAgcmV0dXJuIGNiKGdlbkVycik7XG4gIH1cbn1cblxudmFyIEVycm9yR2VuZXJhdG9yID0gZnVuY3Rpb24gKCkge1xuICBmdW5jdGlvbiBFcnJvckdlbmVyYXRvcigpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgRXJyb3JHZW5lcmF0b3IpO1xuICB9XG5cbiAgX2NyZWF0ZUNsYXNzKEVycm9yR2VuZXJhdG9yLCBbe1xuICAgIGtleTogJ25leHQnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBuZXh0KCkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZ2VuT3JGbiBtdXN0IGJlIGEgZ2VuZXJhdG9yIG9yIGEgZ2VuZXJhdG9yIGZ1bmN0aW9uJyk7XG4gICAgfVxuICB9XSk7XG5cbiAgcmV0dXJuIEVycm9yR2VuZXJhdG9yO1xufSgpO1xuXG5mdW5jdGlvbiBmZXcoZ2VuT3JGbiwgY2IpIHtcbiAgYWR2YW5jZShpc0dlbmVyYXRvcihnZW5PckZuKSA/IGdlbk9yRm4gOiBpc0dlbmVyYXRvckZ1bmN0aW9uKGdlbk9yRm4pID8gZ2VuT3JGbigpIDogbmV3IEVycm9yR2VuZXJhdG9yKCksIGlzRnVuY3Rpb24oY2IpID8gY2IgOiBmdW5jdGlvbiAoZXJyKSB7XG4gICAgaWYgKGVycikgcHJvY2Vzcy5uZXh0VGljayhmdW5jdGlvbiAoKSB7XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfSk7XG4gIH0pO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGZldzsiLCIvLyBzaGltIGZvciB1c2luZyBwcm9jZXNzIGluIGJyb3dzZXJcblxudmFyIHByb2Nlc3MgPSBtb2R1bGUuZXhwb3J0cyA9IHt9O1xudmFyIHF1ZXVlID0gW107XG52YXIgZHJhaW5pbmcgPSBmYWxzZTtcbnZhciBjdXJyZW50UXVldWU7XG52YXIgcXVldWVJbmRleCA9IC0xO1xuXG5mdW5jdGlvbiBjbGVhblVwTmV4dFRpY2soKSB7XG4gICAgZHJhaW5pbmcgPSBmYWxzZTtcbiAgICBpZiAoY3VycmVudFF1ZXVlLmxlbmd0aCkge1xuICAgICAgICBxdWV1ZSA9IGN1cnJlbnRRdWV1ZS5jb25jYXQocXVldWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHF1ZXVlSW5kZXggPSAtMTtcbiAgICB9XG4gICAgaWYgKHF1ZXVlLmxlbmd0aCkge1xuICAgICAgICBkcmFpblF1ZXVlKCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBkcmFpblF1ZXVlKCkge1xuICAgIGlmIChkcmFpbmluZykge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciB0aW1lb3V0ID0gc2V0VGltZW91dChjbGVhblVwTmV4dFRpY2spO1xuICAgIGRyYWluaW5nID0gdHJ1ZTtcblxuICAgIHZhciBsZW4gPSBxdWV1ZS5sZW5ndGg7XG4gICAgd2hpbGUobGVuKSB7XG4gICAgICAgIGN1cnJlbnRRdWV1ZSA9IHF1ZXVlO1xuICAgICAgICBxdWV1ZSA9IFtdO1xuICAgICAgICB3aGlsZSAoKytxdWV1ZUluZGV4IDwgbGVuKSB7XG4gICAgICAgICAgICBpZiAoY3VycmVudFF1ZXVlKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudFF1ZXVlW3F1ZXVlSW5kZXhdLnJ1bigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHF1ZXVlSW5kZXggPSAtMTtcbiAgICAgICAgbGVuID0gcXVldWUubGVuZ3RoO1xuICAgIH1cbiAgICBjdXJyZW50UXVldWUgPSBudWxsO1xuICAgIGRyYWluaW5nID0gZmFsc2U7XG4gICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xufVxuXG5wcm9jZXNzLm5leHRUaWNrID0gZnVuY3Rpb24gKGZ1bikge1xuICAgIHZhciBhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGggLSAxKTtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuICAgICAgICB9XG4gICAgfVxuICAgIHF1ZXVlLnB1c2gobmV3IEl0ZW0oZnVuLCBhcmdzKSk7XG4gICAgaWYgKHF1ZXVlLmxlbmd0aCA9PT0gMSAmJiAhZHJhaW5pbmcpIHtcbiAgICAgICAgc2V0VGltZW91dChkcmFpblF1ZXVlLCAwKTtcbiAgICB9XG59O1xuXG4vLyB2OCBsaWtlcyBwcmVkaWN0aWJsZSBvYmplY3RzXG5mdW5jdGlvbiBJdGVtKGZ1biwgYXJyYXkpIHtcbiAgICB0aGlzLmZ1biA9IGZ1bjtcbiAgICB0aGlzLmFycmF5ID0gYXJyYXk7XG59XG5JdGVtLnByb3RvdHlwZS5ydW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5mdW4uYXBwbHkobnVsbCwgdGhpcy5hcnJheSk7XG59O1xucHJvY2Vzcy50aXRsZSA9ICdicm93c2VyJztcbnByb2Nlc3MuYnJvd3NlciA9IHRydWU7XG5wcm9jZXNzLmVudiA9IHt9O1xucHJvY2Vzcy5hcmd2ID0gW107XG5wcm9jZXNzLnZlcnNpb24gPSAnJzsgLy8gZW1wdHkgc3RyaW5nIHRvIGF2b2lkIHJlZ2V4cCBpc3N1ZXNcbnByb2Nlc3MudmVyc2lvbnMgPSB7fTtcblxuZnVuY3Rpb24gbm9vcCgpIHt9XG5cbnByb2Nlc3Mub24gPSBub29wO1xucHJvY2Vzcy5hZGRMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLm9uY2UgPSBub29wO1xucHJvY2Vzcy5vZmYgPSBub29wO1xucHJvY2Vzcy5yZW1vdmVMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUFsbExpc3RlbmVycyA9IG5vb3A7XG5wcm9jZXNzLmVtaXQgPSBub29wO1xuXG5wcm9jZXNzLmJpbmRpbmcgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5iaW5kaW5nIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG5cbnByb2Nlc3MuY3dkID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gJy8nIH07XG5wcm9jZXNzLmNoZGlyID0gZnVuY3Rpb24gKGRpcikge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5jaGRpciBpcyBub3Qgc3VwcG9ydGVkJyk7XG59O1xucHJvY2Vzcy51bWFzayA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gMDsgfTtcbiJdfQ==\n"],"sourceRoot":"/source/"} --------------------------------------------------------------------------------