| import { |
| isArray, |
| isMaybeThenable |
| } from './utils'; |
| import { |
| noop, |
| reject, |
| fulfill, |
| subscribe, |
| FULFILLED, |
| REJECTED, |
| PENDING, |
| handleMaybeThenable |
| } from './-internal'; |
| |
| import then from './then'; |
| import Promise from './promise'; |
| import originalResolve from './promise/resolve'; |
| import originalThen from './then'; |
| import { makePromise, PROMISE_ID } from './-internal'; |
| |
| function validationError() { |
| return new Error('Array Methods must be provided an Array'); |
| }; |
| |
| export default class Enumerator { |
| constructor(Constructor, input) { |
| this._instanceConstructor = Constructor; |
| this.promise = new Constructor(noop); |
| |
| if (!this.promise[PROMISE_ID]) { |
| makePromise(this.promise); |
| } |
| |
| if (isArray(input)) { |
| this.length = input.length; |
| this._remaining = input.length; |
| |
| this._result = new Array(this.length); |
| |
| if (this.length === 0) { |
| fulfill(this.promise, this._result); |
| } else { |
| this.length = this.length || 0; |
| this._enumerate(input); |
| if (this._remaining === 0) { |
| fulfill(this.promise, this._result); |
| } |
| } |
| } else { |
| reject(this.promise, validationError()); |
| } |
| } |
| _enumerate(input) { |
| for (let i = 0; this._state === PENDING && i < input.length; i++) { |
| this._eachEntry(input[i], i); |
| } |
| } |
| |
| _eachEntry(entry, i) { |
| let c = this._instanceConstructor; |
| let { resolve } = c; |
| |
| if (resolve === originalResolve) { |
| let then; |
| let error; |
| let didError = false; |
| try { |
| then = entry.then; |
| } catch (e) { |
| didError = true; |
| error = e; |
| } |
| |
| if (then === originalThen && |
| entry._state !== PENDING) { |
| this._settledAt(entry._state, i, entry._result); |
| } else if (typeof then !== 'function') { |
| this._remaining--; |
| this._result[i] = entry; |
| } else if (c === Promise) { |
| let promise = new c(noop); |
| if (didError) { |
| reject(promise, error); |
| } else { |
| handleMaybeThenable(promise, entry, then); |
| } |
| this._willSettleAt(promise, i); |
| } else { |
| this._willSettleAt(new c(resolve => resolve(entry)), i); |
| } |
| } else { |
| this._willSettleAt(resolve(entry), i); |
| } |
| } |
| |
| _settledAt(state, i, value) { |
| let { promise } = this; |
| |
| if (promise._state === PENDING) { |
| this._remaining--; |
| |
| if (state === REJECTED) { |
| reject(promise, value); |
| } else { |
| this._result[i] = value; |
| } |
| } |
| |
| if (this._remaining === 0) { |
| fulfill(promise, this._result); |
| } |
| } |
| |
| _willSettleAt(promise, i) { |
| let enumerator = this; |
| |
| subscribe( |
| promise, undefined, |
| value => enumerator._settledAt(FULFILLED, i, value), |
| reason => enumerator._settledAt(REJECTED, i, reason) |
| ); |
| } |
| }; |