blob: a90ba2f9730c548970f71d5722ba811d8527706f [file] [log] [blame]
'use strict';
var iteratorSymbol = require('es6-symbol').iterator
, isArguments = require('../../function/is-arguments')
, isFunction = require('../../function/is-function')
, toPosInt = require('../../number/to-pos-integer')
, callable = require('../../object/valid-callable')
, validValue = require('../../object/valid-value')
, isString = require('../../string/is-string')
, isArray = Array.isArray, call = Function.prototype.call
, desc = { configurable: true, enumerable: true, writable: true, value: null }
, defineProperty = Object.defineProperty;
module.exports = function (arrayLike/*, mapFn, thisArg*/) {
var mapFn = arguments[1], thisArg = arguments[2], Constructor, i, j, arr, l, code, iterator
, result, getIterator, value;
arrayLike = Object(validValue(arrayLike));
if (mapFn != null) callable(mapFn);
if (!this || (this === Array) || !isFunction(this)) {
// Result: Plain array
if (!mapFn) {
if (isArguments(arrayLike)) {
// Source: Arguments
l = arrayLike.length;
if (l !== 1) return Array.apply(null, arrayLike);
arr = new Array(1);
arr[0] = arrayLike[0];
return arr;
}
if (isArray(arrayLike)) {
// Source: Array
arr = new Array(l = arrayLike.length);
for (i = 0; i < l; ++i) arr[i] = arrayLike[i];
return arr;
}
}
arr = [];
} else {
// Result: Non plain array
Constructor = this;
}
if (!isArray(arrayLike)) {
if ((getIterator = arrayLike[iteratorSymbol]) !== undefined) {
// Source: Iterator
iterator = callable(getIterator).call(arrayLike);
if (Constructor) arr = new Constructor();
result = iterator.next();
i = 0;
while (!result.done) {
value = mapFn ? call.call(mapFn, thisArg, result.value, i) : result.value;
if (!Constructor) {
arr[i] = value;
} else {
desc.value = value;
defineProperty(arr, i, desc);
}
result = iterator.next();
++i;
}
l = i;
} else if (isString(arrayLike)) {
// Source: String
l = arrayLike.length;
if (Constructor) arr = new Constructor();
for (i = 0, j = 0; i < l; ++i) {
value = arrayLike[i];
if ((i + 1) < l) {
code = value.charCodeAt(0);
if ((code >= 0xD800) && (code <= 0xDBFF)) value += arrayLike[++i];
}
value = mapFn ? call.call(mapFn, thisArg, value, j) : value;
if (!Constructor) {
arr[j] = value;
} else {
desc.value = value;
defineProperty(arr, j, desc);
}
++j;
}
l = j;
}
}
if (l === undefined) {
// Source: array or array-like
l = toPosInt(arrayLike.length);
if (Constructor) arr = new Constructor(l);
for (i = 0; i < l; ++i) {
value = mapFn ? call.call(mapFn, thisArg, arrayLike[i], i) : arrayLike[i];
if (!Constructor) {
arr[i] = value;
} else {
desc.value = value;
defineProperty(arr, i, desc);
}
}
}
if (Constructor) {
desc.value = null;
arr.length = l;
}
return arr;
};