_iter-define.js 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. 'use strict';
  2. var LIBRARY = require('./_library')
  3. , $export = require('./_export')
  4. , redefine = require('./_redefine')
  5. , hide = require('./_hide')
  6. , has = require('./_has')
  7. , Iterators = require('./_iterators')
  8. , $iterCreate = require('./_iter-create')
  9. , setToStringTag = require('./_set-to-string-tag')
  10. , getPrototypeOf = require('./_object-gpo')
  11. , ITERATOR = require('./_wks')('iterator')
  12. , BUGGY = !([].keys && 'next' in [].keys()) // Safari has buggy iterators w/o `next`
  13. , FF_ITERATOR = '@@iterator'
  14. , KEYS = 'keys'
  15. , 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. , DEF_VALUES = DEFAULT == VALUES
  28. , VALUES_BUG = false
  29. , proto = Base.prototype
  30. , $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT]
  31. , $default = $native || getMethod(DEFAULT)
  32. , $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined
  33. , $anyNative = NAME == 'Array' ? proto.entries || $native : $native
  34. , methods, key, IteratorPrototype;
  35. // Fix native
  36. if($anyNative){
  37. IteratorPrototype = getPrototypeOf($anyNative.call(new Base));
  38. if(IteratorPrototype !== Object.prototype){
  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. };