| 'use strict'; |
| |
| var clear = require('es5-ext/array/#/clear') |
| , assign = require('es5-ext/object/assign') |
| , callable = require('es5-ext/object/valid-callable') |
| , value = require('es5-ext/object/valid-value') |
| , d = require('d') |
| , autoBind = require('d/auto-bind') |
| , Symbol = require('es6-symbol') |
| |
| , defineProperty = Object.defineProperty |
| , defineProperties = Object.defineProperties |
| , Iterator; |
| |
| module.exports = Iterator = function (list, context) { |
| if (!(this instanceof Iterator)) return new Iterator(list, context); |
| defineProperties(this, { |
| __list__: d('w', value(list)), |
| __context__: d('w', context), |
| __nextIndex__: d('w', 0) |
| }); |
| if (!context) return; |
| callable(context.on); |
| context.on('_add', this._onAdd); |
| context.on('_delete', this._onDelete); |
| context.on('_clear', this._onClear); |
| }; |
| |
| defineProperties(Iterator.prototype, assign({ |
| constructor: d(Iterator), |
| _next: d(function () { |
| var i; |
| if (!this.__list__) return; |
| if (this.__redo__) { |
| i = this.__redo__.shift(); |
| if (i !== undefined) return i; |
| } |
| if (this.__nextIndex__ < this.__list__.length) return this.__nextIndex__++; |
| this._unBind(); |
| }), |
| next: d(function () { return this._createResult(this._next()); }), |
| _createResult: d(function (i) { |
| if (i === undefined) return { done: true, value: undefined }; |
| return { done: false, value: this._resolve(i) }; |
| }), |
| _resolve: d(function (i) { return this.__list__[i]; }), |
| _unBind: d(function () { |
| this.__list__ = null; |
| delete this.__redo__; |
| if (!this.__context__) return; |
| this.__context__.off('_add', this._onAdd); |
| this.__context__.off('_delete', this._onDelete); |
| this.__context__.off('_clear', this._onClear); |
| this.__context__ = null; |
| }), |
| toString: d(function () { return '[object Iterator]'; }) |
| }, autoBind({ |
| _onAdd: d(function (index) { |
| if (index >= this.__nextIndex__) return; |
| ++this.__nextIndex__; |
| if (!this.__redo__) { |
| defineProperty(this, '__redo__', d('c', [index])); |
| return; |
| } |
| this.__redo__.forEach(function (redo, i) { |
| if (redo >= index) this.__redo__[i] = ++redo; |
| }, this); |
| this.__redo__.push(index); |
| }), |
| _onDelete: d(function (index) { |
| var i; |
| if (index >= this.__nextIndex__) return; |
| --this.__nextIndex__; |
| if (!this.__redo__) return; |
| i = this.__redo__.indexOf(index); |
| if (i !== -1) this.__redo__.splice(i, 1); |
| this.__redo__.forEach(function (redo, i) { |
| if (redo > index) this.__redo__[i] = --redo; |
| }, this); |
| }), |
| _onClear: d(function () { |
| if (this.__redo__) clear.call(this.__redo__); |
| this.__nextIndex__ = 0; |
| }) |
| }))); |
| |
| defineProperty(Iterator.prototype, Symbol.iterator, d(function () { |
| return this; |
| })); |
| defineProperty(Iterator.prototype, Symbol.toStringTag, d('', 'Iterator')); |