| 'use strict'; |
| var global = require('./_global') |
| , $export = require('./_export') |
| , redefine = require('./_redefine') |
| , redefineAll = require('./_redefine-all') |
| , meta = require('./_meta') |
| , forOf = require('./_for-of') |
| , anInstance = require('./_an-instance') |
| , isObject = require('./_is-object') |
| , fails = require('./_fails') |
| , $iterDetect = require('./_iter-detect') |
| , setToStringTag = require('./_set-to-string-tag') |
| , inheritIfRequired = require('./_inherit-if-required'); |
| |
| module.exports = function(NAME, wrapper, methods, common, IS_MAP, IS_WEAK){ |
| var Base = global[NAME] |
| , C = Base |
| , ADDER = IS_MAP ? 'set' : 'add' |
| , proto = C && C.prototype |
| , O = {}; |
| var fixMethod = function(KEY){ |
| var fn = proto[KEY]; |
| redefine(proto, KEY, |
| KEY == 'delete' ? function(a){ |
| return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a); |
| } : KEY == 'has' ? function has(a){ |
| return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a); |
| } : KEY == 'get' ? function get(a){ |
| return IS_WEAK && !isObject(a) ? undefined : fn.call(this, a === 0 ? 0 : a); |
| } : KEY == 'add' ? function add(a){ fn.call(this, a === 0 ? 0 : a); return this; } |
| : function set(a, b){ fn.call(this, a === 0 ? 0 : a, b); return this; } |
| ); |
| }; |
| if(typeof C != 'function' || !(IS_WEAK || proto.forEach && !fails(function(){ |
| new C().entries().next(); |
| }))){ |
| // create collection constructor |
| C = common.getConstructor(wrapper, NAME, IS_MAP, ADDER); |
| redefineAll(C.prototype, methods); |
| meta.NEED = true; |
| } else { |
| var instance = new C |
| // early implementations not supports chaining |
| , HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) != instance |
| // V8 ~ Chromium 40- weak-collections throws on primitives, but should return false |
| , THROWS_ON_PRIMITIVES = fails(function(){ instance.has(1); }) |
| // most early implementations doesn't supports iterables, most modern - not close it correctly |
| , ACCEPT_ITERABLES = $iterDetect(function(iter){ new C(iter); }) // eslint-disable-line no-new |
| // for early implementations -0 and +0 not the same |
| , BUGGY_ZERO = !IS_WEAK && fails(function(){ |
| // V8 ~ Chromium 42- fails only with 5+ elements |
| var $instance = new C() |
| , index = 5; |
| while(index--)$instance[ADDER](index, index); |
| return !$instance.has(-0); |
| }); |
| if(!ACCEPT_ITERABLES){ |
| C = wrapper(function(target, iterable){ |
| anInstance(target, C, NAME); |
| var that = inheritIfRequired(new Base, target, C); |
| if(iterable != undefined)forOf(iterable, IS_MAP, that[ADDER], that); |
| return that; |
| }); |
| C.prototype = proto; |
| proto.constructor = C; |
| } |
| if(THROWS_ON_PRIMITIVES || BUGGY_ZERO){ |
| fixMethod('delete'); |
| fixMethod('has'); |
| IS_MAP && fixMethod('get'); |
| } |
| if(BUGGY_ZERO || HASNT_CHAINING)fixMethod(ADDER); |
| // weak collections should not contains .clear method |
| if(IS_WEAK && proto.clear)delete proto.clear; |
| } |
| |
| setToStringTag(C, NAME); |
| |
| O[NAME] = C; |
| $export($export.G + $export.W + $export.F * (C != Base), O); |
| |
| if(!IS_WEAK)common.setStrong(C, NAME, IS_MAP); |
| |
| return C; |
| }; |