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'
17 var returnThis = function(){ return this; };
19 module.exports = function(Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED){
20 $iterCreate(Constructor, NAME, next);
21 var getMethod = function(kind){
22 if(!BUGGY && kind in proto)return proto[kind];
24 case KEYS: return function keys(){ return new Constructor(this, kind); };
25 case VALUES: return function values(){ return new Constructor(this, kind); };
26 } return function entries(){ return new Constructor(this, kind); };
28 var TAG = NAME + ' Iterator'
29 , DEF_VALUES = DEFAULT == VALUES
31 , proto = Base.prototype
32 , $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT]
33 , $default = $native || getMethod(DEFAULT)
34 , $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined
35 , $anyNative = NAME == 'Array' ? proto.entries || $native : $native
36 , methods, key, IteratorPrototype;
39 IteratorPrototype = getPrototypeOf($anyNative.call(new Base));
40 if(IteratorPrototype !== Object.prototype){
41 // Set @@toStringTag to native iterators
42 setToStringTag(IteratorPrototype, TAG, true);
43 // fix for some old engines
44 if(!LIBRARY && !has(IteratorPrototype, ITERATOR))hide(IteratorPrototype, ITERATOR, returnThis);
47 // fix Array#{values, @@iterator}.name in V8 / FF
48 if(DEF_VALUES && $native && $native.name !== VALUES){
50 $default = function values(){ return $native.call(this); };
53 if((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])){
54 hide(proto, ITERATOR, $default);
57 Iterators[NAME] = $default;
58 Iterators[TAG] = returnThis;
61 values: DEF_VALUES ? $default : getMethod(VALUES),
62 keys: IS_SET ? $default : getMethod(KEYS),
65 if(FORCED)for(key in methods){
66 if(!(key in proto))redefine(proto, key, methods[key]);
67 } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods);