| 'use strict'; |
| var $ = require('../internals/export'); |
| var global = require('../internals/global'); |
| var isForced = require('../internals/is-forced'); |
| var redefine = require('../internals/redefine'); |
| var InternalMetadataModule = require('../internals/internal-metadata'); |
| var iterate = require('../internals/iterate'); |
| var anInstance = require('../internals/an-instance'); |
| var isObject = require('../internals/is-object'); |
| var fails = require('../internals/fails'); |
| var checkCorrectnessOfIteration = require('../internals/check-correctness-of-iteration'); |
| var setToStringTag = require('../internals/set-to-string-tag'); |
| var inheritIfRequired = require('../internals/inherit-if-required'); |
| |
| module.exports = function (CONSTRUCTOR_NAME, wrapper, common, IS_MAP, IS_WEAK) { |
| var NativeConstructor = global[CONSTRUCTOR_NAME]; |
| var NativePrototype = NativeConstructor && NativeConstructor.prototype; |
| var Constructor = NativeConstructor; |
| var ADDER = IS_MAP ? 'set' : 'add'; |
| var exported = {}; |
| |
| var fixMethod = function (KEY) { |
| var nativeMethod = NativePrototype[KEY]; |
| redefine(NativePrototype, KEY, |
| KEY == 'add' ? function add(value) { |
| nativeMethod.call(this, value === 0 ? 0 : value); |
| return this; |
| } : KEY == 'delete' ? function (key) { |
| return IS_WEAK && !isObject(key) ? false : nativeMethod.call(this, key === 0 ? 0 : key); |
| } : KEY == 'get' ? function get(key) { |
| return IS_WEAK && !isObject(key) ? undefined : nativeMethod.call(this, key === 0 ? 0 : key); |
| } : KEY == 'has' ? function has(key) { |
| return IS_WEAK && !isObject(key) ? false : nativeMethod.call(this, key === 0 ? 0 : key); |
| } : function set(key, value) { |
| nativeMethod.call(this, key === 0 ? 0 : key, value); |
| return this; |
| } |
| ); |
| }; |
| |
| // eslint-disable-next-line max-len |
| if (isForced(CONSTRUCTOR_NAME, typeof NativeConstructor != 'function' || !(IS_WEAK || NativePrototype.forEach && !fails(function () { |
| new NativeConstructor().entries().next(); |
| })))) { |
| // create collection constructor |
| Constructor = common.getConstructor(wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER); |
| InternalMetadataModule.REQUIRED = true; |
| } else if (isForced(CONSTRUCTOR_NAME, true)) { |
| var instance = new Constructor(); |
| // early implementations not supports chaining |
| var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) != instance; |
| // V8 ~ Chromium 40- weak-collections throws on primitives, but should return false |
| var THROWS_ON_PRIMITIVES = fails(function () { instance.has(1); }); |
| // most early implementations doesn't supports iterables, most modern - not close it correctly |
| // eslint-disable-next-line no-new |
| var ACCEPT_ITERABLES = checkCorrectnessOfIteration(function (iterable) { new NativeConstructor(iterable); }); |
| // for early implementations -0 and +0 not the same |
| var BUGGY_ZERO = !IS_WEAK && fails(function () { |
| // V8 ~ Chromium 42- fails only with 5+ elements |
| var $instance = new NativeConstructor(); |
| var index = 5; |
| while (index--) $instance[ADDER](index, index); |
| return !$instance.has(-0); |
| }); |
| |
| if (!ACCEPT_ITERABLES) { |
| Constructor = wrapper(function (dummy, iterable) { |
| anInstance(dummy, Constructor, CONSTRUCTOR_NAME); |
| var that = inheritIfRequired(new NativeConstructor(), dummy, Constructor); |
| if (iterable != undefined) iterate(iterable, that[ADDER], that, IS_MAP); |
| return that; |
| }); |
| Constructor.prototype = NativePrototype; |
| NativePrototype.constructor = Constructor; |
| } |
| |
| 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 && NativePrototype.clear) delete NativePrototype.clear; |
| } |
| |
| exported[CONSTRUCTOR_NAME] = Constructor; |
| $({ global: true, forced: Constructor != NativeConstructor }, exported); |
| |
| setToStringTag(Constructor, CONSTRUCTOR_NAME); |
| |
| if (!IS_WEAK) common.setStrong(Constructor, CONSTRUCTOR_NAME, IS_MAP); |
| |
| return Constructor; |
| }; |