107 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			107 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| "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");
 | |
| 
 | |
| var defineProperty = Object.defineProperty, defineProperties = Object.defineProperties, Iterator;
 | |
| 
 | |
| module.exports = Iterator = function (list, context) {
 | |
| 	if (!(this instanceof Iterator)) throw new TypeError("Constructor requires 'new'");
 | |
| 	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);
 | |
| };
 | |
| 
 | |
| // Internal %IteratorPrototype% doesn't expose its constructor
 | |
| delete Iterator.prototype.constructor;
 | |
| 
 | |
| defineProperties(
 | |
| 	Iterator.prototype,
 | |
| 	assign(
 | |
| 		{
 | |
| 			_next: d(function () {
 | |
| 				var i;
 | |
| 				if (!this.__list__) return undefined;
 | |
| 				if (this.__redo__) {
 | |
| 					i = this.__redo__.shift();
 | |
| 					if (i !== undefined) return i;
 | |
| 				}
 | |
| 				if (this.__nextIndex__ < this.__list__.length) return this.__nextIndex__++;
 | |
| 				this._unBind();
 | |
| 				return undefined;
 | |
| 			}),
 | |
| 			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 " + (this[Symbol.toStringTag] || "Object") + "]";
 | |
| 			})
 | |
| 		},
 | |
| 		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, j) {
 | |
| 					if (redo > index) this.__redo__[j] = --redo;
 | |
| 				}, this);
 | |
| 			}),
 | |
| 			_onClear: d(function () {
 | |
| 				if (this.__redo__) clear.call(this.__redo__);
 | |
| 				this.__nextIndex__ = 0;
 | |
| 			})
 | |
| 		})
 | |
| 	)
 | |
| );
 | |
| 
 | |
| defineProperty(
 | |
| 	Iterator.prototype,
 | |
| 	Symbol.iterator,
 | |
| 	d(function () {
 | |
| 		return this;
 | |
| 	})
 | |
| );
 |