index.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. "use strict";
  2. var clear = require("es5-ext/array/#/clear")
  3. , assign = require("es5-ext/object/assign")
  4. , callable = require("es5-ext/object/valid-callable")
  5. , value = require("es5-ext/object/valid-value")
  6. , d = require("d")
  7. , autoBind = require("d/auto-bind")
  8. , Symbol = require("es6-symbol");
  9. var defineProperty = Object.defineProperty, defineProperties = Object.defineProperties, Iterator;
  10. module.exports = Iterator = function (list, context) {
  11. if (!(this instanceof Iterator)) throw new TypeError("Constructor requires 'new'");
  12. defineProperties(this, {
  13. __list__: d("w", value(list)),
  14. __context__: d("w", context),
  15. __nextIndex__: d("w", 0)
  16. });
  17. if (!context) return;
  18. callable(context.on);
  19. context.on("_add", this._onAdd);
  20. context.on("_delete", this._onDelete);
  21. context.on("_clear", this._onClear);
  22. };
  23. // Internal %IteratorPrototype% doesn't expose its constructor
  24. delete Iterator.prototype.constructor;
  25. defineProperties(
  26. Iterator.prototype,
  27. assign(
  28. {
  29. _next: d(function () {
  30. var i;
  31. if (!this.__list__) return undefined;
  32. if (this.__redo__) {
  33. i = this.__redo__.shift();
  34. if (i !== undefined) return i;
  35. }
  36. if (this.__nextIndex__ < this.__list__.length) return this.__nextIndex__++;
  37. this._unBind();
  38. return undefined;
  39. }),
  40. next: d(function () {
  41. return this._createResult(this._next());
  42. }),
  43. _createResult: d(function (i) {
  44. if (i === undefined) return { done: true, value: undefined };
  45. return { done: false, value: this._resolve(i) };
  46. }),
  47. _resolve: d(function (i) {
  48. return this.__list__[i];
  49. }),
  50. _unBind: d(function () {
  51. this.__list__ = null;
  52. delete this.__redo__;
  53. if (!this.__context__) return;
  54. this.__context__.off("_add", this._onAdd);
  55. this.__context__.off("_delete", this._onDelete);
  56. this.__context__.off("_clear", this._onClear);
  57. this.__context__ = null;
  58. }),
  59. toString: d(function () {
  60. return "[object " + (this[Symbol.toStringTag] || "Object") + "]";
  61. })
  62. },
  63. autoBind({
  64. _onAdd: d(function (index) {
  65. if (index >= this.__nextIndex__) return;
  66. ++this.__nextIndex__;
  67. if (!this.__redo__) {
  68. defineProperty(this, "__redo__", d("c", [index]));
  69. return;
  70. }
  71. this.__redo__.forEach(function (redo, i) {
  72. if (redo >= index) this.__redo__[i] = ++redo;
  73. }, this);
  74. this.__redo__.push(index);
  75. }),
  76. _onDelete: d(function (index) {
  77. var i;
  78. if (index >= this.__nextIndex__) return;
  79. --this.__nextIndex__;
  80. if (!this.__redo__) return;
  81. i = this.__redo__.indexOf(index);
  82. if (i !== -1) this.__redo__.splice(i, 1);
  83. this.__redo__.forEach(function (redo, j) {
  84. if (redo > index) this.__redo__[j] = --redo;
  85. }, this);
  86. }),
  87. _onClear: d(function () {
  88. if (this.__redo__) clear.call(this.__redo__);
  89. this.__nextIndex__ = 0;
  90. })
  91. })
  92. )
  93. );
  94. defineProperty(
  95. Iterator.prototype,
  96. Symbol.iterator,
  97. d(function () {
  98. return this;
  99. })
  100. );