_iter-define.js 2.7 KB

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