| 'use strict'; |
| var LIBRARY = require('./_library') |
| , $export = require('./_export') |
| , redefine = require('./_redefine') |
| , hide = require('./_hide') |
| , has = require('./_has') |
| , Iterators = require('./_iterators') |
| , $iterCreate = require('./_iter-create') |
| , setToStringTag = require('./_set-to-string-tag') |
| , getPrototypeOf = require('./_object-gpo') |
| , ITERATOR = require('./_wks')('iterator') |
| , BUGGY = !([].keys && 'next' in [].keys()) // Safari has buggy iterators w/o `next` |
| , FF_ITERATOR = '@@iterator' |
| , KEYS = 'keys' |
| , VALUES = 'values'; |
| |
| var returnThis = function(){ return this; }; |
| |
| module.exports = function(Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED){ |
| $iterCreate(Constructor, NAME, next); |
| var getMethod = function(kind){ |
| if(!BUGGY && kind in proto)return proto[kind]; |
| switch(kind){ |
| case KEYS: return function keys(){ return new Constructor(this, kind); }; |
| case VALUES: return function values(){ return new Constructor(this, kind); }; |
| } return function entries(){ return new Constructor(this, kind); }; |
| }; |
| var TAG = NAME + ' Iterator' |
| , DEF_VALUES = DEFAULT == VALUES |
| , VALUES_BUG = false |
| , proto = Base.prototype |
| , $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT] |
| , $default = $native || getMethod(DEFAULT) |
| , $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined |
| , $anyNative = NAME == 'Array' ? proto.entries || $native : $native |
| , methods, key, IteratorPrototype; |
| // Fix native |
| if($anyNative){ |
| IteratorPrototype = getPrototypeOf($anyNative.call(new Base)); |
| if(IteratorPrototype !== Object.prototype){ |
| // Set @@toStringTag to native iterators |
| setToStringTag(IteratorPrototype, TAG, true); |
| // fix for some old engines |
| if(!LIBRARY && !has(IteratorPrototype, ITERATOR))hide(IteratorPrototype, ITERATOR, returnThis); |
| } |
| } |
| // fix Array#{values, @@iterator}.name in V8 / FF |
| if(DEF_VALUES && $native && $native.name !== VALUES){ |
| VALUES_BUG = true; |
| $default = function values(){ return $native.call(this); }; |
| } |
| // Define iterator |
| if((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])){ |
| hide(proto, ITERATOR, $default); |
| } |
| // Plug for library |
| Iterators[NAME] = $default; |
| Iterators[TAG] = returnThis; |
| if(DEFAULT){ |
| methods = { |
| values: DEF_VALUES ? $default : getMethod(VALUES), |
| keys: IS_SET ? $default : getMethod(KEYS), |
| entries: $entries |
| }; |
| if(FORCED)for(key in methods){ |
| if(!(key in proto))redefine(proto, key, methods[key]); |
| } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods); |
| } |
| return methods; |
| }; |