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