You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
85 lines
3.3 KiB
JavaScript
85 lines
3.3 KiB
JavaScript
7 years ago
|
'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;
|
||
|
};
|