2 var $ = require('../internals/export');
3 var global = require('../internals/global');
4 var uncurryThis = require('../internals/function-uncurry-this');
5 var isForced = require('../internals/is-forced');
6 var redefine = require('../internals/redefine');
7 var InternalMetadataModule = require('../internals/internal-metadata');
8 var iterate = require('../internals/iterate');
9 var anInstance = require('../internals/an-instance');
10 var isCallable = require('../internals/is-callable');
11 var isObject = require('../internals/is-object');
12 var fails = require('../internals/fails');
13 var checkCorrectnessOfIteration = require('../internals/check-correctness-of-iteration');
14 var setToStringTag = require('../internals/set-to-string-tag');
15 var inheritIfRequired = require('../internals/inherit-if-required');
17 module.exports = function (CONSTRUCTOR_NAME, wrapper, common) {
18 var IS_MAP = CONSTRUCTOR_NAME.indexOf('Map') !== -1;
19 var IS_WEAK = CONSTRUCTOR_NAME.indexOf('Weak') !== -1;
20 var ADDER = IS_MAP ? 'set' : 'add';
21 var NativeConstructor = global[CONSTRUCTOR_NAME];
22 var NativePrototype = NativeConstructor && NativeConstructor.prototype;
23 var Constructor = NativeConstructor;
26 var fixMethod = function (KEY) {
27 var uncurriedNativeMethod = uncurryThis(NativePrototype[KEY]);
28 redefine(NativePrototype, KEY,
29 KEY == 'add' ? function add(value) {
30 uncurriedNativeMethod(this, value === 0 ? 0 : value);
32 } : KEY == 'delete' ? function (key) {
33 return IS_WEAK && !isObject(key) ? false : uncurriedNativeMethod(this, key === 0 ? 0 : key);
34 } : KEY == 'get' ? function get(key) {
35 return IS_WEAK && !isObject(key) ? undefined : uncurriedNativeMethod(this, key === 0 ? 0 : key);
36 } : KEY == 'has' ? function has(key) {
37 return IS_WEAK && !isObject(key) ? false : uncurriedNativeMethod(this, key === 0 ? 0 : key);
38 } : function set(key, value) {
39 uncurriedNativeMethod(this, key === 0 ? 0 : key, value);
45 var REPLACE = isForced(
47 !isCallable(NativeConstructor) || !(IS_WEAK || NativePrototype.forEach && !fails(function () {
48 new NativeConstructor().entries().next();
53 // create collection constructor
54 Constructor = common.getConstructor(wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER);
55 InternalMetadataModule.enable();
56 } else if (isForced(CONSTRUCTOR_NAME, true)) {
57 var instance = new Constructor();
58 // early implementations not supports chaining
59 var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) != instance;
60 // V8 ~ Chromium 40- weak-collections throws on primitives, but should return false
61 var THROWS_ON_PRIMITIVES = fails(function () { instance.has(1); });
62 // most early implementations doesn't supports iterables, most modern - not close it correctly
63 // eslint-disable-next-line no-new -- required for testing
64 var ACCEPT_ITERABLES = checkCorrectnessOfIteration(function (iterable) { new NativeConstructor(iterable); });
65 // for early implementations -0 and +0 not the same
66 var BUGGY_ZERO = !IS_WEAK && fails(function () {
67 // V8 ~ Chromium 42- fails only with 5+ elements
68 var $instance = new NativeConstructor();
70 while (index--) $instance[ADDER](index, index);
71 return !$instance.has(-0);
74 if (!ACCEPT_ITERABLES) {
75 Constructor = wrapper(function (dummy, iterable) {
76 anInstance(dummy, NativePrototype);
77 var that = inheritIfRequired(new NativeConstructor(), dummy, Constructor);
78 if (iterable != undefined) iterate(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });
81 Constructor.prototype = NativePrototype;
82 NativePrototype.constructor = Constructor;
85 if (THROWS_ON_PRIMITIVES || BUGGY_ZERO) {
88 IS_MAP && fixMethod('get');
91 if (BUGGY_ZERO || HASNT_CHAINING) fixMethod(ADDER);
93 // weak collections should not contains .clear method
94 if (IS_WEAK && NativePrototype.clear) delete NativePrototype.clear;
97 exported[CONSTRUCTOR_NAME] = Constructor;
98 $({ global: true, forced: Constructor != NativeConstructor }, exported);
100 setToStringTag(Constructor, CONSTRUCTOR_NAME);
102 if (!IS_WEAK) common.setStrong(Constructor, CONSTRUCTOR_NAME, IS_MAP);