$.iter-define.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  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. , getProto = require('./$').getProto
  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. , methods, key;
  33. // Fix native
  34. if($native){
  35. var IteratorPrototype = getProto($default.call(new Base));
  36. // Set @@toStringTag to native iterators
  37. setToStringTag(IteratorPrototype, TAG, true);
  38. // FF fix
  39. if(!LIBRARY && has(proto, FF_ITERATOR))hide(IteratorPrototype, ITERATOR, returnThis);
  40. // fix Array#{values, @@iterator}.name in V8 / FF
  41. if(DEF_VALUES && $native.name !== VALUES){
  42. VALUES_BUG = true;
  43. $default = function values(){ return $native.call(this); };
  44. }
  45. }
  46. // Define iterator
  47. if((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])){
  48. hide(proto, ITERATOR, $default);
  49. }
  50. // Plug for library
  51. Iterators[NAME] = $default;
  52. Iterators[TAG] = returnThis;
  53. if(DEFAULT){
  54. methods = {
  55. values: DEF_VALUES ? $default : getMethod(VALUES),
  56. keys: IS_SET ? $default : getMethod(KEYS),
  57. entries: !DEF_VALUES ? $default : getMethod('entries')
  58. };
  59. if(FORCED)for(key in methods){
  60. if(!(key in proto))redefine(proto, key, methods[key]);
  61. } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods);
  62. }
  63. return methods;
  64. };