2 var global = require('./_global')
3 , $export = require('./_export')
4 , redefine = require('./_redefine')
5 , redefineAll = require('./_redefine-all')
6 , meta = require('./_meta')
7 , forOf = require('./_for-of')
8 , anInstance = require('./_an-instance')
9 , isObject = require('./_is-object')
10 , fails = require('./_fails')
11 , $iterDetect = require('./_iter-detect')
12 , setToStringTag = require('./_set-to-string-tag')
13 , inheritIfRequired = require('./_inherit-if-required');
15 module.exports = function(NAME, wrapper, methods, common, IS_MAP, IS_WEAK){
16 var Base = global[NAME]
18 , ADDER = IS_MAP ? 'set' : 'add'
19 , proto = C && C.prototype
21 var fixMethod = function(KEY){
24 KEY == 'delete' ? function(a){
25 return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);
26 } : KEY == 'has' ? function has(a){
27 return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);
28 } : KEY == 'get' ? function get(a){
29 return IS_WEAK && !isObject(a) ? undefined : fn.call(this, a === 0 ? 0 : a);
30 } : KEY == 'add' ? function add(a){ fn.call(this, a === 0 ? 0 : a); return this; }
31 : function set(a, b){ fn.call(this, a === 0 ? 0 : a, b); return this; }
34 if(typeof C != 'function' || !(IS_WEAK || proto.forEach && !fails(function(){
35 new C().entries().next();
37 // create collection constructor
38 C = common.getConstructor(wrapper, NAME, IS_MAP, ADDER);
39 redefineAll(C.prototype, methods);
43 // early implementations not supports chaining
44 , HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) != instance
45 // V8 ~ Chromium 40- weak-collections throws on primitives, but should return false
46 , THROWS_ON_PRIMITIVES = fails(function(){ instance.has(1); })
47 // most early implementations doesn't supports iterables, most modern - not close it correctly
48 , ACCEPT_ITERABLES = $iterDetect(function(iter){ new C(iter); }) // eslint-disable-line no-new
49 // for early implementations -0 and +0 not the same
50 , BUGGY_ZERO = !IS_WEAK && fails(function(){
51 // V8 ~ Chromium 42- fails only with 5+ elements
52 var $instance = new C()
54 while(index--)$instance[ADDER](index, index);
55 return !$instance.has(-0);
57 if(!ACCEPT_ITERABLES){
58 C = wrapper(function(target, iterable){
59 anInstance(target, C, NAME);
60 var that = inheritIfRequired(new Base, target, C);
61 if(iterable != undefined)forOf(iterable, IS_MAP, that[ADDER], that);
65 proto.constructor = C;
67 if(THROWS_ON_PRIMITIVES || BUGGY_ZERO){
70 IS_MAP && fixMethod('get');
72 if(BUGGY_ZERO || HASNT_CHAINING)fixMethod(ADDER);
73 // weak collections should not contains .clear method
74 if(IS_WEAK && proto.clear)delete proto.clear;
77 setToStringTag(C, NAME);
80 $export($export.G + $export.W + $export.F * (C != Base), O);
82 if(!IS_WEAK)common.setStrong(C, NAME, IS_MAP);