iterator-define.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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/iterator-create-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 defineBuiltIn = require('../internals/define-built-in');
  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 && 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. }
  35. return function () { return new IteratorConstructor(this); };
  36. };
  37. var TO_STRING_TAG = NAME + ' Iterator';
  38. var INCORRECT_VALUES_NAME = false;
  39. var IterablePrototype = Iterable.prototype;
  40. var nativeIterator = IterablePrototype[ITERATOR]
  41. || IterablePrototype['@@iterator']
  42. || DEFAULT && IterablePrototype[DEFAULT];
  43. var defaultIterator = !BUGGY_SAFARI_ITERATORS && nativeIterator || getIterationMethod(DEFAULT);
  44. var anyNativeIterator = NAME === 'Array' ? IterablePrototype.entries || nativeIterator : nativeIterator;
  45. var CurrentIteratorPrototype, methods, KEY;
  46. // fix native
  47. if (anyNativeIterator) {
  48. CurrentIteratorPrototype = getPrototypeOf(anyNativeIterator.call(new Iterable()));
  49. if (CurrentIteratorPrototype !== Object.prototype && CurrentIteratorPrototype.next) {
  50. if (!IS_PURE && getPrototypeOf(CurrentIteratorPrototype) !== IteratorPrototype) {
  51. if (setPrototypeOf) {
  52. setPrototypeOf(CurrentIteratorPrototype, IteratorPrototype);
  53. } else if (!isCallable(CurrentIteratorPrototype[ITERATOR])) {
  54. defineBuiltIn(CurrentIteratorPrototype, ITERATOR, returnThis);
  55. }
  56. }
  57. // Set @@toStringTag to native iterators
  58. setToStringTag(CurrentIteratorPrototype, TO_STRING_TAG, true, true);
  59. if (IS_PURE) Iterators[TO_STRING_TAG] = returnThis;
  60. }
  61. }
  62. // fix Array.prototype.{ values, @@iterator }.name in V8 / FF
  63. if (PROPER_FUNCTION_NAME && DEFAULT === VALUES && nativeIterator && nativeIterator.name !== VALUES) {
  64. if (!IS_PURE && CONFIGURABLE_FUNCTION_NAME) {
  65. createNonEnumerableProperty(IterablePrototype, 'name', VALUES);
  66. } else {
  67. INCORRECT_VALUES_NAME = true;
  68. defaultIterator = function values() { return call(nativeIterator, this); };
  69. }
  70. }
  71. // export additional methods
  72. if (DEFAULT) {
  73. methods = {
  74. values: getIterationMethod(VALUES),
  75. keys: IS_SET ? defaultIterator : getIterationMethod(KEYS),
  76. entries: getIterationMethod(ENTRIES)
  77. };
  78. if (FORCED) for (KEY in methods) {
  79. if (BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME || !(KEY in IterablePrototype)) {
  80. defineBuiltIn(IterablePrototype, KEY, methods[KEY]);
  81. }
  82. } else $({ target: NAME, proto: true, forced: BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME }, methods);
  83. }
  84. // define iterator
  85. if ((!IS_PURE || FORCED) && IterablePrototype[ITERATOR] !== defaultIterator) {
  86. defineBuiltIn(IterablePrototype, ITERATOR, defaultIterator, { name: DEFAULT });
  87. }
  88. Iterators[NAME] = defaultIterator;
  89. return methods;
  90. };