120 lines
3.1 KiB
JavaScript
120 lines
3.1 KiB
JavaScript
"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")
|
|
, isValue = require("../../object/is-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;
|
|
|
|
// eslint-disable-next-line complexity, max-lines-per-function
|
|
module.exports = function (arrayLike /*, mapFn, thisArg*/) {
|
|
var mapFn = arguments[1]
|
|
, thisArg = arguments[2]
|
|
, Context
|
|
, i
|
|
, j
|
|
, arr
|
|
, length
|
|
, code
|
|
, iterator
|
|
, result
|
|
, getIterator
|
|
, value;
|
|
|
|
arrayLike = Object(validValue(arrayLike));
|
|
|
|
if (isValue(mapFn)) callable(mapFn);
|
|
if (!this || this === Array || !isFunction(this)) {
|
|
// Result: Plain array
|
|
if (!mapFn) {
|
|
if (isArguments(arrayLike)) {
|
|
// Source: Arguments
|
|
length = arrayLike.length;
|
|
if (length !== 1) return Array.apply(null, arrayLike);
|
|
arr = new Array(1);
|
|
arr[0] = arrayLike[0];
|
|
return arr;
|
|
}
|
|
if (isArray(arrayLike)) {
|
|
// Source: Array
|
|
arr = new Array((length = arrayLike.length));
|
|
for (i = 0; i < length; ++i) arr[i] = arrayLike[i];
|
|
return arr;
|
|
}
|
|
}
|
|
arr = [];
|
|
} else {
|
|
// Result: Non plain array
|
|
Context = this;
|
|
}
|
|
|
|
if (!isArray(arrayLike)) {
|
|
if ((getIterator = arrayLike[iteratorSymbol]) !== undefined) {
|
|
// Source: Iterator
|
|
iterator = callable(getIterator).call(arrayLike);
|
|
if (Context) arr = new Context();
|
|
result = iterator.next();
|
|
i = 0;
|
|
while (!result.done) {
|
|
value = mapFn ? call.call(mapFn, thisArg, result.value, i) : result.value;
|
|
if (Context) {
|
|
desc.value = value;
|
|
defineProperty(arr, i, desc);
|
|
} else {
|
|
arr[i] = value;
|
|
}
|
|
result = iterator.next();
|
|
++i;
|
|
}
|
|
length = i;
|
|
} else if (isString(arrayLike)) {
|
|
// Source: String
|
|
length = arrayLike.length;
|
|
if (Context) arr = new Context();
|
|
for (i = 0, j = 0; i < length; ++i) {
|
|
value = arrayLike[i];
|
|
if (i + 1 < length) {
|
|
code = value.charCodeAt(0);
|
|
// eslint-disable-next-line max-depth
|
|
if (code >= 0xd800 && code <= 0xdbff) value += arrayLike[++i];
|
|
}
|
|
value = mapFn ? call.call(mapFn, thisArg, value, j) : value;
|
|
if (Context) {
|
|
desc.value = value;
|
|
defineProperty(arr, j, desc);
|
|
} else {
|
|
arr[j] = value;
|
|
}
|
|
++j;
|
|
}
|
|
length = j;
|
|
}
|
|
}
|
|
if (length === undefined) {
|
|
// Source: array or array-like
|
|
length = toPosInt(arrayLike.length);
|
|
if (Context) arr = new Context(length);
|
|
for (i = 0; i < length; ++i) {
|
|
value = mapFn ? call.call(mapFn, thisArg, arrayLike[i], i) : arrayLike[i];
|
|
if (Context) {
|
|
desc.value = value;
|
|
defineProperty(arr, i, desc);
|
|
} else {
|
|
arr[i] = value;
|
|
}
|
|
}
|
|
}
|
|
if (Context) {
|
|
desc.value = null;
|
|
arr.length = length;
|
|
}
|
|
return arr;
|
|
};
|