3 var clear = require('es5-ext/array/#/clear')
4 , assign = require('es5-ext/object/assign')
5 , callable = require('es5-ext/object/valid-callable')
6 , value = require('es5-ext/object/valid-value')
8 , autoBind = require('d/auto-bind')
9 , Symbol = require('es6-symbol')
11 , defineProperty = Object.defineProperty
12 , defineProperties = Object.defineProperties
15 module.exports = Iterator = function (list, context) {
16 if (!(this instanceof Iterator)) return new Iterator(list, context);
17 defineProperties(this, {
18 __list__: d('w', value(list)),
19 __context__: d('w', context),
20 __nextIndex__: d('w', 0)
24 context.on('_add', this._onAdd);
25 context.on('_delete', this._onDelete);
26 context.on('_clear', this._onClear);
29 defineProperties(Iterator.prototype, assign({
30 constructor: d(Iterator),
31 _next: d(function () {
33 if (!this.__list__) return;
35 i = this.__redo__.shift();
36 if (i !== undefined) return i;
38 if (this.__nextIndex__ < this.__list__.length) return this.__nextIndex__++;
41 next: d(function () { return this._createResult(this._next()); }),
42 _createResult: d(function (i) {
43 if (i === undefined) return { done: true, value: undefined };
44 return { done: false, value: this._resolve(i) };
46 _resolve: d(function (i) { return this.__list__[i]; }),
47 _unBind: d(function () {
50 if (!this.__context__) return;
51 this.__context__.off('_add', this._onAdd);
52 this.__context__.off('_delete', this._onDelete);
53 this.__context__.off('_clear', this._onClear);
54 this.__context__ = null;
56 toString: d(function () { return '[object Iterator]'; })
58 _onAdd: d(function (index) {
59 if (index >= this.__nextIndex__) return;
62 defineProperty(this, '__redo__', d('c', [index]));
65 this.__redo__.forEach(function (redo, i) {
66 if (redo >= index) this.__redo__[i] = ++redo;
68 this.__redo__.push(index);
70 _onDelete: d(function (index) {
72 if (index >= this.__nextIndex__) return;
74 if (!this.__redo__) return;
75 i = this.__redo__.indexOf(index);
76 if (i !== -1) this.__redo__.splice(i, 1);
77 this.__redo__.forEach(function (redo, i) {
78 if (redo > index) this.__redo__[i] = --redo;
81 _onClear: d(function () {
82 if (this.__redo__) clear.call(this.__redo__);
83 this.__nextIndex__ = 0;
87 defineProperty(Iterator.prototype, Symbol.iterator, d(function () {
90 defineProperty(Iterator.prototype, Symbol.toStringTag, d('', 'Iterator'));