numeric-range-iterator.js 3.4 KB

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