| var anObject = require('../internals/an-object'); |
| var isArrayIteratorMethod = require('../internals/is-array-iterator-method'); |
| var toLength = require('../internals/to-length'); |
| var bind = require('../internals/function-bind-context'); |
| var getIteratorMethod = require('../internals/get-iterator-method'); |
| var iteratorClose = require('../internals/iterator-close'); |
| |
| var Result = function (stopped, result) { |
| this.stopped = stopped; |
| this.result = result; |
| }; |
| |
| module.exports = function (iterable, unboundFunction, options) { |
| var that = options && options.that; |
| var AS_ENTRIES = !!(options && options.AS_ENTRIES); |
| var IS_ITERATOR = !!(options && options.IS_ITERATOR); |
| var INTERRUPTED = !!(options && options.INTERRUPTED); |
| var fn = bind(unboundFunction, that, 1 + AS_ENTRIES + INTERRUPTED); |
| var iterator, iterFn, index, length, result, next, step; |
| |
| var stop = function (condition) { |
| if (iterator) iteratorClose(iterator); |
| return new Result(true, condition); |
| }; |
| |
| var callFn = function (value) { |
| if (AS_ENTRIES) { |
| anObject(value); |
| return INTERRUPTED ? fn(value[0], value[1], stop) : fn(value[0], value[1]); |
| } return INTERRUPTED ? fn(value, stop) : fn(value); |
| }; |
| |
| if (IS_ITERATOR) { |
| iterator = iterable; |
| } else { |
| iterFn = getIteratorMethod(iterable); |
| if (typeof iterFn != 'function') throw TypeError('Target is not iterable'); |
| // optimisation for array iterators |
| if (isArrayIteratorMethod(iterFn)) { |
| for (index = 0, length = toLength(iterable.length); length > index; index++) { |
| result = callFn(iterable[index]); |
| if (result && result instanceof Result) return result; |
| } return new Result(false); |
| } |
| iterator = iterFn.call(iterable); |
| } |
| |
| next = iterator.next; |
| while (!(step = next.call(iterator)).done) { |
| try { |
| result = callFn(step.value); |
| } catch (error) { |
| iteratorClose(iterator); |
| throw error; |
| } |
| if (typeof result == 'object' && result && result instanceof Result) return result; |
| } return new Result(false); |
| }; |