numeric-range-iterator.js 3.6 KB

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