numeric-range-iterator.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. 'use strict';
  2. var InternalStateModule = require('../internals/internal-state');
  3. var createIteratorConstructor = require('../internals/iterator-create-constructor');
  4. var createIterResultObject = require('../internals/create-iter-result-object');
  5. var isNullOrUndefined = require('../internals/is-null-or-undefined');
  6. var isObject = require('../internals/is-object');
  7. var defineProperties = require('../internals/object-define-properties').f;
  8. var DESCRIPTORS = require('../internals/descriptors');
  9. var INCORRECT_RANGE = 'Incorrect Number.range arguments';
  10. var NUMERIC_RANGE_ITERATOR = 'NumericRangeIterator';
  11. var setInternalState = InternalStateModule.set;
  12. var getInternalState = InternalStateModule.getterFor(NUMERIC_RANGE_ITERATOR);
  13. var $RangeError = RangeError;
  14. var $TypeError = TypeError;
  15. var $RangeIterator = createIteratorConstructor(function NumericRangeIterator(start, end, option, type, zero, one) {
  16. if (typeof start != type || (end !== Infinity && end !== -Infinity && typeof end != type)) {
  17. throw $TypeError(INCORRECT_RANGE);
  18. }
  19. if (start === Infinity || start === -Infinity) {
  20. throw $RangeError(INCORRECT_RANGE);
  21. }
  22. var ifIncrease = end > start;
  23. var inclusiveEnd = false;
  24. var step;
  25. if (option === undefined) {
  26. step = undefined;
  27. } else if (isObject(option)) {
  28. step = option.step;
  29. inclusiveEnd = !!option.inclusive;
  30. } else if (typeof option == type) {
  31. step = option;
  32. } else {
  33. throw $TypeError(INCORRECT_RANGE);
  34. }
  35. if (isNullOrUndefined(step)) {
  36. step = ifIncrease ? one : -one;
  37. }
  38. if (typeof step != type) {
  39. throw $TypeError(INCORRECT_RANGE);
  40. }
  41. if (step === Infinity || step === -Infinity || (step === zero && start !== end)) {
  42. throw $RangeError(INCORRECT_RANGE);
  43. }
  44. // eslint-disable-next-line no-self-compare -- NaN check
  45. var hitsEnd = start != start || end != end || step != step || (end > start) !== (step > zero);
  46. setInternalState(this, {
  47. type: NUMERIC_RANGE_ITERATOR,
  48. start: start,
  49. end: end,
  50. step: step,
  51. inclusiveEnd: inclusiveEnd,
  52. hitsEnd: hitsEnd,
  53. currentCount: zero,
  54. zero: zero
  55. });
  56. if (!DESCRIPTORS) {
  57. this.start = start;
  58. this.end = end;
  59. this.step = step;
  60. this.inclusive = inclusiveEnd;
  61. }
  62. }, NUMERIC_RANGE_ITERATOR, function next() {
  63. var state = getInternalState(this);
  64. if (state.hitsEnd) return createIterResultObject(undefined, true);
  65. var start = state.start;
  66. var end = state.end;
  67. var step = state.step;
  68. var currentYieldingValue = start + (step * state.currentCount++);
  69. if (currentYieldingValue === end) state.hitsEnd = true;
  70. var inclusiveEnd = state.inclusiveEnd;
  71. var endCondition;
  72. if (end > start) {
  73. endCondition = inclusiveEnd ? currentYieldingValue > end : currentYieldingValue >= end;
  74. } else {
  75. endCondition = inclusiveEnd ? end > currentYieldingValue : end >= currentYieldingValue;
  76. }
  77. if (endCondition) {
  78. state.hitsEnd = true;
  79. return createIterResultObject(undefined, true);
  80. } return createIterResultObject(currentYieldingValue, false);
  81. });
  82. var getter = function (fn) {
  83. return { get: fn, set: function () { /* empty */ }, configurable: true, enumerable: false };
  84. };
  85. if (DESCRIPTORS) {
  86. defineProperties($RangeIterator.prototype, {
  87. start: getter(function () {
  88. return getInternalState(this).start;
  89. }),
  90. end: getter(function () {
  91. return getInternalState(this).end;
  92. }),
  93. inclusive: getter(function () {
  94. return getInternalState(this).inclusiveEnd;
  95. }),
  96. step: getter(function () {
  97. return getInternalState(this).step;
  98. })
  99. });
  100. }
  101. module.exports = $RangeIterator;