define-iterator.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. 'use strict';
  2. var $ = require('../internals/export');
  3. var call = require('../internals/function-call');
  4. var IS_PURE = require('../internals/is-pure');
  5. var FunctionName = require('../internals/function-name');
  6. var isCallable = require('../internals/is-callable');
  7. var createIteratorConstructor = require('../internals/create-iterator-constructor');
  8. var getPrototypeOf = require('../internals/object-get-prototype-of');
  9. var setPrototypeOf = require('../internals/object-set-prototype-of');
  10. var setToStringTag = require('../internals/set-to-string-tag');
  11. var createNonEnumerableProperty = require('../internals/create-non-enumerable-property');
  12. var redefine = require('../internals/redefine');
  13. var wellKnownSymbol = require('../internals/well-known-symbol');
  14. var Iterators = require('../internals/iterators');
  15. var IteratorsCore = require('../internals/iterators-core');
  16. var PROPER_FUNCTION_NAME = FunctionName.PROPER;
  17. var CONFIGURABLE_FUNCTION_NAME = FunctionName.CONFIGURABLE;
  18. var IteratorPrototype = IteratorsCore.IteratorPrototype;
  19. var BUGGY_SAFARI_ITERATORS = IteratorsCore.BUGGY_SAFARI_ITERATORS;
  20. var ITERATOR = wellKnownSymbol('iterator');
  21. var KEYS = 'keys';
  22. var VALUES = 'values';
  23. var ENTRIES = 'entries';
  24. var returnThis = function () { return this; };
  25. module.exports = function (Iterable, NAME, IteratorConstructor, next, DEFAULT, IS_SET, FORCED) {
  26. createIteratorConstructor(IteratorConstructor, NAME, next);
  27. var getIterationMethod = function (KIND) {
  28. if (KIND === DEFAULT && defaultIterator) return defaultIterator;
  29. if (!BUGGY_SAFARI_ITERATORS && KIND in IterablePrototype) return IterablePrototype[KIND];
  30. switch (KIND) {
  31. case KEYS: return function keys() { return new IteratorConstructor(this, KIND); };
  32. case VALUES: return function values() { return new IteratorConstructor(this, KIND); };
  33. case ENTRIES: return function entries() { return new IteratorConstructor(this, KIND); };
  34. } return function () { return new IteratorConstructor(this); };
  35. };
  36. var TO_STRING_TAG = NAME + ' Iterator';
  37. var INCORRECT_VALUES_NAME = false;
  38. var IterablePrototype = Iterable.prototype;
  39. var nativeIterator = IterablePrototype[ITERATOR]
  40. || IterablePrototype['@@iterator']
  41. || DEFAULT && IterablePrototype[DEFAULT];
  42. var defaultIterator = !BUGGY_SAFARI_ITERATORS && nativeIterator || getIterationMethod(DEFAULT);
  43. var anyNativeIterator = NAME == 'Array' ? IterablePrototype.entries || nativeIterator : nativeIterator;
  44. var CurrentIteratorPrototype, methods, KEY;
  45. // fix native
  46. if (anyNativeIterator) {
  47. CurrentIteratorPrototype = getPrototypeOf(anyNativeIterator.call(new Iterable()));
  48. if (CurrentIteratorPrototype !== Object.prototype && CurrentIteratorPrototype.next) {
  49. if (!IS_PURE && getPrototypeOf(CurrentIteratorPrototype) !== IteratorPrototype) {
  50. if (setPrototypeOf) {
  51. setPrototypeOf(CurrentIteratorPrototype, IteratorPrototype);
  52. } else if (!isCallable(CurrentIteratorPrototype[ITERATOR])) {
  53. redefine(CurrentIteratorPrototype, ITERATOR, returnThis);
  54. }
  55. }
  56. // Set @@toStringTag to native iterators
  57. setToStringTag(CurrentIteratorPrototype, TO_STRING_TAG, true, true);
  58. if (IS_PURE) Iterators[TO_STRING_TAG] = returnThis;
  59. }
  60. }
  61. // fix Array.prototype.{ values, @@iterator }.name in V8 / FF
  62. if (PROPER_FUNCTION_NAME && DEFAULT == VALUES && nativeIterator && nativeIterator.name !== VALUES) {
  63. if (!IS_PURE && CONFIGURABLE_FUNCTION_NAME) {
  64. createNonEnumerableProperty(IterablePrototype, 'name', VALUES);
  65. } else {
  66. INCORRECT_VALUES_NAME = true;
  67. defaultIterator = function values() { return call(nativeIterator, this); };
  68. }
  69. }
  70. // export additional methods
  71. if (DEFAULT) {
  72. methods = {
  73. values: getIterationMethod(VALUES),
  74. keys: IS_SET ? defaultIterator : getIterationMethod(KEYS),
  75. entries: getIterationMethod(ENTRIES)
  76. };
  77. if (FORCED) for (KEY in methods) {
  78. if (BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME || !(KEY in IterablePrototype)) {
  79. redefine(IterablePrototype, KEY, methods[KEY]);
  80. }
  81. } else $({ target: NAME, proto: true, forced: BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME }, methods);
  82. }
  83. // define iterator
  84. if ((!IS_PURE || FORCED) && IterablePrototype[ITERATOR] !== defaultIterator) {
  85. redefine(IterablePrototype, ITERATOR, defaultIterator, { name: DEFAULT });
  86. }
  87. Iterators[NAME] = defaultIterator;
  88. return methods;
  89. };