You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
119 lines
3.1 KiB
119 lines
3.1 KiB
"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; |
|
};
|
|
|