190 lines
5.7 KiB
JavaScript
190 lines
5.7 KiB
JavaScript
'use strict';
|
|
|
|
/* eslint global-require: 0 */
|
|
// the code is structured this way so that bundlers can
|
|
// alias out `has-symbols` to `() => true` or `() => false` if your target
|
|
// environments' Symbol capabilities are known, and then use
|
|
// dead code elimination on the rest of this module.
|
|
//
|
|
// Similarly, `isarray` can be aliased to `Array.isArray` if
|
|
// available in all target environments.
|
|
|
|
var isArguments = require('is-arguments');
|
|
var getStopIterationIterator = require('stop-iteration-iterator');
|
|
|
|
if (require('has-symbols')() || require('has-symbols/shams')()) {
|
|
var $iterator = Symbol.iterator;
|
|
// Symbol is available natively or shammed
|
|
// natively:
|
|
// - Chrome >= 38
|
|
// - Edge 12-14?, Edge >= 15 for sure
|
|
// - FF >= 36
|
|
// - Safari >= 9
|
|
// - node >= 0.12
|
|
module.exports = function getIterator(iterable) {
|
|
// alternatively, `iterable[$iterator]?.()`
|
|
if (iterable != null && typeof iterable[$iterator] !== 'undefined') {
|
|
return iterable[$iterator]();
|
|
}
|
|
if (isArguments(iterable)) {
|
|
// arguments objects lack Symbol.iterator
|
|
// - node 0.12
|
|
return Array.prototype[$iterator].call(iterable);
|
|
}
|
|
};
|
|
} else {
|
|
// Symbol is not available, native or shammed
|
|
var isArray = require('isarray');
|
|
var isString = require('is-string');
|
|
var GetIntrinsic = require('get-intrinsic');
|
|
var $Map = GetIntrinsic('%Map%', true);
|
|
var $Set = GetIntrinsic('%Set%', true);
|
|
var callBound = require('call-bind/callBound');
|
|
var $arrayPush = callBound('Array.prototype.push');
|
|
var $charCodeAt = callBound('String.prototype.charCodeAt');
|
|
var $stringSlice = callBound('String.prototype.slice');
|
|
|
|
var advanceStringIndex = function advanceStringIndex(S, index) {
|
|
var length = S.length;
|
|
if ((index + 1) >= length) {
|
|
return index + 1;
|
|
}
|
|
|
|
var first = $charCodeAt(S, index);
|
|
if (first < 0xD800 || first > 0xDBFF) {
|
|
return index + 1;
|
|
}
|
|
|
|
var second = $charCodeAt(S, index + 1);
|
|
if (second < 0xDC00 || second > 0xDFFF) {
|
|
return index + 1;
|
|
}
|
|
|
|
return index + 2;
|
|
};
|
|
|
|
var getArrayIterator = function getArrayIterator(arraylike) {
|
|
var i = 0;
|
|
return {
|
|
next: function next() {
|
|
var done = i >= arraylike.length;
|
|
var value;
|
|
if (!done) {
|
|
value = arraylike[i];
|
|
i += 1;
|
|
}
|
|
return {
|
|
done: done,
|
|
value: value
|
|
};
|
|
}
|
|
};
|
|
};
|
|
|
|
var getNonCollectionIterator = function getNonCollectionIterator(iterable, noPrimordialCollections) {
|
|
if (isArray(iterable) || isArguments(iterable)) {
|
|
return getArrayIterator(iterable);
|
|
}
|
|
if (isString(iterable)) {
|
|
var i = 0;
|
|
return {
|
|
next: function next() {
|
|
var nextIndex = advanceStringIndex(iterable, i);
|
|
var value = $stringSlice(iterable, i, nextIndex);
|
|
i = nextIndex;
|
|
return {
|
|
done: nextIndex > iterable.length,
|
|
value: value
|
|
};
|
|
}
|
|
};
|
|
}
|
|
|
|
// es6-shim and es-shims' es-map use a string "_es6-shim iterator_" property on different iterables, such as MapIterator.
|
|
if (noPrimordialCollections && typeof iterable['_es6-shim iterator_'] !== 'undefined') {
|
|
return iterable['_es6-shim iterator_']();
|
|
}
|
|
};
|
|
|
|
if (!$Map && !$Set) {
|
|
// the only language iterables are Array, String, arguments
|
|
// - Safari <= 6.0
|
|
// - Chrome < 38
|
|
// - node < 0.12
|
|
// - FF < 13
|
|
// - IE < 11
|
|
// - Edge < 11
|
|
|
|
module.exports = function getIterator(iterable) {
|
|
if (iterable != null) {
|
|
return getNonCollectionIterator(iterable, true);
|
|
}
|
|
};
|
|
} else {
|
|
// either Map or Set are available, but Symbol is not
|
|
// - es6-shim on an ES5 browser
|
|
// - Safari 6.2 (maybe 6.1?)
|
|
// - FF v[13, 36)
|
|
// - IE 11
|
|
// - Edge 11
|
|
// - Safari v[6, 9)
|
|
|
|
var isMap = require('is-map');
|
|
var isSet = require('is-set');
|
|
|
|
// Firefox >= 27, IE 11, Safari 6.2 - 9, Edge 11, es6-shim in older envs, all have forEach
|
|
var $mapForEach = callBound('Map.prototype.forEach', true);
|
|
var $setForEach = callBound('Set.prototype.forEach', true);
|
|
if (typeof process === 'undefined' || !process.versions || !process.versions.node) { // "if is not node"
|
|
|
|
// Firefox 17 - 26 has `.iterator()`, whose iterator `.next()` either
|
|
// returns a value, or throws a StopIteration object. These browsers
|
|
// do not have any other mechanism for iteration.
|
|
var $mapIterator = callBound('Map.prototype.iterator', true);
|
|
var $setIterator = callBound('Set.prototype.iterator', true);
|
|
}
|
|
// Firefox 27-35, and some older es6-shim versions, use a string "@@iterator" property
|
|
// this returns a proper iterator object, so we should use it instead of forEach.
|
|
// newer es6-shim versions use a string "_es6-shim iterator_" property.
|
|
var $mapAtAtIterator = callBound('Map.prototype.@@iterator', true) || callBound('Map.prototype._es6-shim iterator_', true);
|
|
var $setAtAtIterator = callBound('Set.prototype.@@iterator', true) || callBound('Set.prototype._es6-shim iterator_', true);
|
|
|
|
var getCollectionIterator = function getCollectionIterator(iterable) {
|
|
if (isMap(iterable)) {
|
|
if ($mapIterator) {
|
|
return getStopIterationIterator($mapIterator(iterable));
|
|
}
|
|
if ($mapAtAtIterator) {
|
|
return $mapAtAtIterator(iterable);
|
|
}
|
|
if ($mapForEach) {
|
|
var entries = [];
|
|
$mapForEach(iterable, function (v, k) {
|
|
$arrayPush(entries, [k, v]);
|
|
});
|
|
return getArrayIterator(entries);
|
|
}
|
|
}
|
|
if (isSet(iterable)) {
|
|
if ($setIterator) {
|
|
return getStopIterationIterator($setIterator(iterable));
|
|
}
|
|
if ($setAtAtIterator) {
|
|
return $setAtAtIterator(iterable);
|
|
}
|
|
if ($setForEach) {
|
|
var values = [];
|
|
$setForEach(iterable, function (v) {
|
|
$arrayPush(values, v);
|
|
});
|
|
return getArrayIterator(values);
|
|
}
|
|
}
|
|
};
|
|
|
|
module.exports = function getIterator(iterable) {
|
|
return getCollectionIterator(iterable) || getNonCollectionIterator(iterable);
|
|
};
|
|
}
|
|
}
|