66 lines
2.5 KiB
JavaScript
66 lines
2.5 KiB
JavaScript
'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')
|
|
, getProto = require('./$').getProto
|
|
, 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)
|
|
, methods, key;
|
|
// Fix native
|
|
if($native){
|
|
var IteratorPrototype = getProto($default.call(new Base));
|
|
// Set @@toStringTag to native iterators
|
|
setToStringTag(IteratorPrototype, TAG, true);
|
|
// FF fix
|
|
if(!LIBRARY && has(proto, FF_ITERATOR))hide(IteratorPrototype, ITERATOR, returnThis);
|
|
// fix Array#{values, @@iterator}.name in V8 / FF
|
|
if(DEF_VALUES && $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: !DEF_VALUES ? $default : getMethod('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;
|
|
}; |