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.
107 lines
2.9 KiB
107 lines
2.9 KiB
4 years ago
|
"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;
|
||
|
})
|
||
|
);
|