/* globals IsCallable, GetMethod, Symbol, IsConstructor, Construct, ArrayCreate, GetIterator, IteratorClose, ToString, IteratorStep, IteratorValue, Call, CreateDataPropertyOrThrow, ToObject, ToLength, Get, CreateMethodProperty */ (function () { // Detection if ('from' in Array && (function () { try { Array.from({ length: -Infinity }); if (Array.from(new self.Set(['a']))[0] !== 'a') { return false; } if (Array.from(new self.Map([['a', 'one']]))[0][0] !== 'a') { return false; } return true; } catch (e) { return false; } }())) { return; } var toString = Object.prototype.toString; var stringMatch = String.prototype.match; // A cross-realm friendly way to detect if a value is a String object or literal. function isString(value) { if (typeof value === 'string') { return true; } if (typeof value !== 'object') { return false; } return toString.call(value) === '[object String]'; } // 22.1.2.1. Array.from ( items [ , mapfn [ , thisArg ] ] ) CreateMethodProperty(Array, 'from', function from(items /* [ , mapfn [ , thisArg ] ] */) { // eslint-disable-line no-undef // 1. Let C be the this value. var C = this; // 2. If mapfn is undefined, let mapping be false. var mapfn = arguments.length > 1 ? arguments[1] : undefined; if (mapfn === undefined) { var mapping = false; // 3. Else, } else { // a. If IsCallable(mapfn) is false, throw a TypeError exception. if (IsCallable(mapfn) === false) { throw new TypeError(Object.prototype.toString.call(mapfn) + ' is not a function.'); } // b. If thisArg is present, let T be thisArg; else let T be undefined. var thisArg = arguments.length > 2 ? arguments[2] : undefined; if (thisArg !== undefined) { var T = thisArg; } else { T = undefined; } // c. Let mapping be true. mapping = true; } // 4. Let usingIterator be ? GetMethod(items, @@iterator). var usingIterator = GetMethod(items, Symbol.iterator); // 5. If usingIterator is not undefined, then if (usingIterator !== undefined) { // a. If IsConstructor(C) is true, then if (IsConstructor(C)) { // i. Let A be ? Construct(C). var A = Construct(C); // b. Else, } else { // i. Let A be ! ArrayCreate(0). A = ArrayCreate(0); } // c. Let iteratorRecord be ? GetIterator(items, usingIterator). var iteratorRecord = GetIterator(items, usingIterator); // d. Let k be 0. var k = 0; // e. Repeat, // eslint-disable-next-line no-constant-condition while (true) { // i. If k ≥ 2^53-1, then if (k >= (Math.pow(2, 53) - 1)) { // 1. Let error be Completion{[[Type]]: throw, [[Value]]: a newly created TypeError object, [[Target]]: empty}. var error = new TypeError('Iteration count can not be greater than or equal 9007199254740991.'); // 2. Return ? IteratorClose(iteratorRecord, error). return IteratorClose(iteratorRecord, error); } // ii. Let Pk be ! ToString(k). var Pk = ToString(k); // iii. Let next be ? IteratorStep(iteratorRecord). var next = IteratorStep(iteratorRecord); // iv. If next is false, then if (next === false) { // 1. Perform ? Set(A, "length", k, true). A.length = k; // 2. Return A. return A; } // v. Let nextValue be ? IteratorValue(next). var nextValue = IteratorValue(next); // vi. If mapping is true, then if (mapping) { try { // Polyfill.io - The try catch accounts for step 2. // 1. Let mappedValue be Call(mapfn, T, « nextValue, k »). var mappedValue = Call(mapfn, T, [nextValue, k]); // 2. If mappedValue is an abrupt completion, return ? IteratorClose(iteratorRecord, mappedValue). // 3. Let mappedValue be mappedValue.[[Value]]. } catch (e) { return IteratorClose(iteratorRecord, e); } // vii. Else, let mappedValue be nextValue. } else { mappedValue = nextValue; } try { // Polyfill.io - The try catch accounts for step ix. // viii. Let defineStatus be CreateDataPropertyOrThrow(A, Pk, mappedValue). CreateDataPropertyOrThrow(A, Pk, mappedValue); // ix. If defineStatus is an abrupt completion, return ? IteratorClose(iteratorRecord, defineStatus). } catch (e) { return IteratorClose(iteratorRecord, e); } // x. Increase k by 1. k = k + 1; } } // 6. NOTE: items is not an Iterable so assume it is an array-like object. // 7. Let arrayLike be ! ToObject(items). // Polyfill.io - For Strings we need to split astral symbols into surrogate pairs. if (isString(items)) { var arrayLike = stringMatch.call(items, /[\uD800-\uDBFF][\uDC00-\uDFFF]?|[^\uD800-\uDFFF]|./g) || []; } else { arrayLike = ToObject(items); } // 8. Let len be ? ToLength(? Get(arrayLike, "length")). var len = ToLength(Get(arrayLike, "length")); // 9. If IsConstructor(C) is true, then if (IsConstructor(C)) { // a. Let A be ? Construct(C, « len »). A = Construct(C, [len]); // 10. Else, } else { // a. Let A be ? ArrayCreate(len). A = ArrayCreate(len); } // 11. Let k be 0. k = 0; // 12. Repeat, while k < len while (k < len) { // a. Let Pk be ! ToString(k). Pk = ToString(k); // b. Let kValue be ? Get(arrayLike, Pk). var kValue = Get(arrayLike, Pk); // c. If mapping is true, then if (mapping === true) { // i. Let mappedValue be ? Call(mapfn, T, « kValue, k »). mappedValue = Call(mapfn, T, [kValue, k]); // d. Else, let mappedValue be kValue. } else { mappedValue = kValue; } // e. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue). CreateDataPropertyOrThrow(A, Pk, mappedValue); // f. Increase k by 1. k = k + 1; } // 13. Perform ? Set(A, "length", len, true). A.length = len; // 14. Return A. return A; }); }());