_iter-define.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. 'use strict';
  2. var LIBRARY = require('./_library');
  3. var $export = require('./_export');
  4. var redefine = require('./_redefine');
  5. var hide = require('./_hide');
  6. var Iterators = require('./_iterators');
  7. var $iterCreate = require('./_iter-create');
  8. var setToStringTag = require('./_set-to-string-tag');
  9. var getPrototypeOf = require('./_object-gpo');
  10. var ITERATOR = require('./_wks')('iterator');
  11. var BUGGY = !([].keys && 'next' in [].keys()); // Safari has buggy iterators w/o `next`
  12. var FF_ITERATOR = '@@iterator';
  13. var KEYS = 'keys';
  14. var VALUES = 'values';
  15. var returnThis = function () { return this; };
  16. module.exports = function (Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED) {
  17. $iterCreate(Constructor, NAME, next);
  18. var getMethod = function (kind) {
  19. if (!BUGGY && kind in proto) return proto[kind];
  20. switch (kind) {
  21. case KEYS: return function keys() { return new Constructor(this, kind); };
  22. case VALUES: return function values() { return new Constructor(this, kind); };
  23. } return function entries() { return new Constructor(this, kind); };
  24. };
  25. var TAG = NAME + ' Iterator';
  26. var DEF_VALUES = DEFAULT == VALUES;
  27. var VALUES_BUG = false;
  28. var proto = Base.prototype;
  29. var $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT];
  30. var $default = $native || getMethod(DEFAULT);
  31. var $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined;
  32. var $anyNative = NAME == 'Array' ? proto.entries || $native : $native;
  33. var methods, key, IteratorPrototype;
  34. // Fix native
  35. if ($anyNative) {
  36. IteratorPrototype = getPrototypeOf($anyNative.call(new Base()));
  37. if (IteratorPrototype !== Object.prototype && IteratorPrototype.next) {
  38. // Set @@toStringTag to native iterators
  39. setToStringTag(IteratorPrototype, TAG, true);
  40. // fix for some old engines
  41. if (!LIBRARY && typeof IteratorPrototype[ITERATOR] != 'function') hide(IteratorPrototype, ITERATOR, returnThis);
  42. }
  43. }
  44. // fix Array#{values, @@iterator}.name in V8 / FF
  45. if (DEF_VALUES && $native && $native.name !== VALUES) {
  46. VALUES_BUG = true;
  47. $default = function values() { return $native.call(this); };
  48. }
  49. // Define iterator
  50. if ((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])) {
  51. hide(proto, ITERATOR, $default);
  52. }
  53. // Plug for library
  54. Iterators[NAME] = $default;
  55. Iterators[TAG] = returnThis;
  56. if (DEFAULT) {
  57. methods = {
  58. values: DEF_VALUES ? $default : getMethod(VALUES),
  59. keys: IS_SET ? $default : getMethod(KEYS),
  60. entries: $entries
  61. };
  62. if (FORCED) for (key in methods) {
  63. if (!(key in proto)) redefine(proto, key, methods[key]);
  64. } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods);
  65. }
  66. return methods;
  67. };