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