You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
3.4 KiB
105 lines
3.4 KiB
'use strict'; |
|
var InternalStateModule = require('../internals/internal-state'); |
|
var createIteratorConstructor = require('../internals/create-iterator-constructor'); |
|
var isObject = require('../internals/is-object'); |
|
var defineProperties = require('../internals/object-define-properties').f; |
|
var DESCRIPTORS = require('../internals/descriptors'); |
|
|
|
var INCORRECT_RANGE = 'Incorrect Number.range arguments'; |
|
var NUMERIC_RANGE_ITERATOR = 'NumericRangeIterator'; |
|
|
|
var setInternalState = InternalStateModule.set; |
|
var getInternalState = InternalStateModule.getterFor(NUMERIC_RANGE_ITERATOR); |
|
|
|
var $RangeError = RangeError; |
|
var $TypeError = TypeError; |
|
|
|
var $RangeIterator = createIteratorConstructor(function NumericRangeIterator(start, end, option, type, zero, one) { |
|
if (typeof start != type || (end !== Infinity && end !== -Infinity && typeof end != type)) { |
|
throw new $TypeError(INCORRECT_RANGE); |
|
} |
|
if (start === Infinity || start === -Infinity) { |
|
throw new $RangeError(INCORRECT_RANGE); |
|
} |
|
var ifIncrease = end > start; |
|
var inclusiveEnd = false; |
|
var step; |
|
if (option === undefined) { |
|
step = undefined; |
|
} else if (isObject(option)) { |
|
step = option.step; |
|
inclusiveEnd = !!option.inclusive; |
|
} else if (typeof option == type) { |
|
step = option; |
|
} else { |
|
throw new $TypeError(INCORRECT_RANGE); |
|
} |
|
if (step == null) { |
|
step = ifIncrease ? one : -one; |
|
} |
|
if (typeof step != type) { |
|
throw new $TypeError(INCORRECT_RANGE); |
|
} |
|
if (step === Infinity || step === -Infinity || (step === zero && start !== end)) { |
|
throw new $RangeError(INCORRECT_RANGE); |
|
} |
|
// eslint-disable-next-line no-self-compare -- NaN check |
|
var hitsEnd = start != start || end != end || step != step || (end > start) !== (step > zero); |
|
setInternalState(this, { |
|
type: NUMERIC_RANGE_ITERATOR, |
|
start: start, |
|
end: end, |
|
step: step, |
|
inclusiveEnd: inclusiveEnd, |
|
hitsEnd: hitsEnd, |
|
currentCount: zero, |
|
zero: zero |
|
}); |
|
if (!DESCRIPTORS) { |
|
this.start = start; |
|
this.end = end; |
|
this.step = step; |
|
this.inclusive = inclusiveEnd; |
|
} |
|
}, NUMERIC_RANGE_ITERATOR, function next() { |
|
var state = getInternalState(this); |
|
if (state.hitsEnd) return { value: undefined, done: true }; |
|
var start = state.start; |
|
var end = state.end; |
|
var step = state.step; |
|
var currentYieldingValue = start + (step * state.currentCount++); |
|
if (currentYieldingValue === end) state.hitsEnd = true; |
|
var inclusiveEnd = state.inclusiveEnd; |
|
var endCondition; |
|
if (end > start) { |
|
endCondition = inclusiveEnd ? currentYieldingValue > end : currentYieldingValue >= end; |
|
} else { |
|
endCondition = inclusiveEnd ? end > currentYieldingValue : end >= currentYieldingValue; |
|
} |
|
if (endCondition) { |
|
return { value: undefined, done: state.hitsEnd = true }; |
|
} return { value: currentYieldingValue, done: false }; |
|
}); |
|
|
|
var getter = function (fn) { |
|
return { get: fn, set: function () { /* empty */ }, configurable: true, enumerable: false }; |
|
}; |
|
|
|
if (DESCRIPTORS) { |
|
defineProperties($RangeIterator.prototype, { |
|
start: getter(function () { |
|
return getInternalState(this).start; |
|
}), |
|
end: getter(function () { |
|
return getInternalState(this).end; |
|
}), |
|
inclusive: getter(function () { |
|
return getInternalState(this).inclusiveEnd; |
|
}), |
|
step: getter(function () { |
|
return getInternalState(this).step; |
|
}) |
|
}); |
|
} |
|
|
|
module.exports = $RangeIterator;
|
|
|