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