| "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; |
| }; |