You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
106 lines
2.9 KiB
106 lines
2.9 KiB
"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; |
|
}) |
|
);
|
|
|