polyfill.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. // Production steps of ECMA-262, Edition 6, 22.1.2.1
  2. // Reference: http://www.ecma-international.org/ecma-262/6.0/#sec-array.from
  3. module.exports = (function() {
  4. var isCallable = function(fn) {
  5. return typeof fn === 'function';
  6. };
  7. var toInteger = function (value) {
  8. var number = Number(value);
  9. if (isNaN(number)) { return 0; }
  10. if (number === 0 || !isFinite(number)) { return number; }
  11. return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
  12. };
  13. var maxSafeInteger = Math.pow(2, 53) - 1;
  14. var toLength = function (value) {
  15. var len = toInteger(value);
  16. return Math.min(Math.max(len, 0), maxSafeInteger);
  17. };
  18. var iteratorProp = function(value) {
  19. if(value != null) {
  20. if(['string','number','boolean','symbol'].indexOf(typeof value) > -1){
  21. return Symbol.iterator;
  22. } else if (
  23. (typeof Symbol !== 'undefined') &&
  24. ('iterator' in Symbol) &&
  25. (Symbol.iterator in value)
  26. ) {
  27. return Symbol.iterator;
  28. }
  29. // Support "@@iterator" placeholder, Gecko 27 to Gecko 35
  30. else if ('@@iterator' in value) {
  31. return '@@iterator';
  32. }
  33. }
  34. };
  35. var getMethod = function(O, P) {
  36. // Assert: IsPropertyKey(P) is true.
  37. if (O != null && P != null) {
  38. // Let func be GetV(O, P).
  39. var func = O[P];
  40. // ReturnIfAbrupt(func).
  41. // If func is either undefined or null, return undefined.
  42. if(func == null) {
  43. return void 0;
  44. }
  45. // If IsCallable(func) is false, throw a TypeError exception.
  46. if (!isCallable(func)) {
  47. throw new TypeError(func + ' is not a function');
  48. }
  49. return func;
  50. }
  51. };
  52. var iteratorStep = function(iterator) {
  53. // Let result be IteratorNext(iterator).
  54. // ReturnIfAbrupt(result).
  55. var result = iterator.next();
  56. // Let done be IteratorComplete(result).
  57. // ReturnIfAbrupt(done).
  58. var done = Boolean(result.done);
  59. // If done is true, return false.
  60. if(done) {
  61. return false;
  62. }
  63. // Return result.
  64. return result;
  65. };
  66. // The length property of the from method is 1.
  67. return function from(items /*, mapFn, thisArg */ ) {
  68. 'use strict';
  69. // 1. Let C be the this value.
  70. var C = this;
  71. // 2. If mapfn is undefined, let mapping be false.
  72. var mapFn = arguments.length > 1 ? arguments[1] : void 0;
  73. var T;
  74. if (typeof mapFn !== 'undefined') {
  75. // 3. else
  76. // a. If IsCallable(mapfn) is false, throw a TypeError exception.
  77. if (!isCallable(mapFn)) {
  78. throw new TypeError(
  79. 'Array.from: when provided, the second argument must be a function'
  80. );
  81. }
  82. // b. If thisArg was supplied, let T be thisArg; else let T
  83. // be undefined.
  84. if (arguments.length > 2) {
  85. T = arguments[2];
  86. }
  87. // c. Let mapping be true (implied by mapFn)
  88. }
  89. var A, k;
  90. // 4. Let usingIterator be GetMethod(items, @@iterator).
  91. // 5. ReturnIfAbrupt(usingIterator).
  92. var usingIterator = getMethod(items, iteratorProp(items));
  93. // 6. If usingIterator is not undefined, then
  94. if (usingIterator !== void 0) {
  95. // a. If IsConstructor(C) is true, then
  96. // i. Let A be the result of calling the [[Construct]]
  97. // internal method of C with an empty argument list.
  98. // b. Else,
  99. // i. Let A be the result of the abstract operation ArrayCreate
  100. // with argument 0.
  101. // c. ReturnIfAbrupt(A).
  102. A = isCallable(C) ? Object(new C()) : [];
  103. // d. Let iterator be GetIterator(items, usingIterator).
  104. var iterator = usingIterator.call(items);
  105. // e. ReturnIfAbrupt(iterator).
  106. if (iterator == null) {
  107. throw new TypeError(
  108. 'Array.from requires an array-like or iterable object'
  109. );
  110. }
  111. // f. Let k be 0.
  112. k = 0;
  113. // g. Repeat
  114. var next, nextValue;
  115. while (true) {
  116. // i. Let Pk be ToString(k).
  117. // ii. Let next be IteratorStep(iterator).
  118. // iii. ReturnIfAbrupt(next).
  119. next = iteratorStep(iterator);
  120. // iv. If next is false, then
  121. if (!next) {
  122. // 1. Let setStatus be Set(A, "length", k, true).
  123. // 2. ReturnIfAbrupt(setStatus).
  124. A.length = k;
  125. // 3. Return A.
  126. return A;
  127. }
  128. // v. Let nextValue be IteratorValue(next).
  129. // vi. ReturnIfAbrupt(nextValue)
  130. nextValue = next.value;
  131. // vii. If mapping is true, then
  132. // 1. Let mappedValue be Call(mapfn, T, «nextValue, k»).
  133. // 2. If mappedValue is an abrupt completion, return
  134. // IteratorClose(iterator, mappedValue).
  135. // 3. Let mappedValue be mappedValue.[[value]].
  136. // viii. Else, let mappedValue be nextValue.
  137. // ix. Let defineStatus be the result of
  138. // CreateDataPropertyOrThrow(A, Pk, mappedValue).
  139. // x. [TODO] If defineStatus is an abrupt completion, return
  140. // IteratorClose(iterator, defineStatus).
  141. if (mapFn) {
  142. A[k] = mapFn.call(T, nextValue, k);
  143. }
  144. else {
  145. A[k] = nextValue;
  146. }
  147. // xi. Increase k by 1.
  148. k++;
  149. }
  150. // 7. Assert: items is not an Iterable so assume it is
  151. // an array-like object.
  152. } else {
  153. // 8. Let arrayLike be ToObject(items).
  154. var arrayLike = Object(items);
  155. // 9. ReturnIfAbrupt(items).
  156. if (items == null) {
  157. throw new TypeError(
  158. 'Array.from requires an array-like object - not null or undefined'
  159. );
  160. }
  161. // 10. Let len be ToLength(Get(arrayLike, "length")).
  162. // 11. ReturnIfAbrupt(len).
  163. var len = toLength(arrayLike.length);
  164. // 12. If IsConstructor(C) is true, then
  165. // a. Let A be Construct(C, «len»).
  166. // 13. Else
  167. // a. Let A be ArrayCreate(len).
  168. // 14. ReturnIfAbrupt(A).
  169. A = isCallable(C) ? Object(new C(len)) : new Array(len);
  170. // 15. Let k be 0.
  171. k = 0;
  172. // 16. Repeat, while k < len… (also steps a - h)
  173. var kValue;
  174. while (k < len) {
  175. kValue = arrayLike[k];
  176. if (mapFn) {
  177. A[k] = mapFn.call(T, kValue, k);
  178. }
  179. else {
  180. A[k] = kValue;
  181. }
  182. k++;
  183. }
  184. // 17. Let setStatus be Set(A, "length", len, true).
  185. // 18. ReturnIfAbrupt(setStatus).
  186. A.length = len;
  187. // 19. Return A.
  188. }
  189. return A;
  190. };
  191. })();