100 lines
4.2 KiB
JavaScript
100 lines
4.2 KiB
JavaScript
'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) {
|
|
var IS_MAP = CONSTRUCTOR_NAME.indexOf('Map') !== -1;
|
|
var IS_WEAK = CONSTRUCTOR_NAME.indexOf('Weak') !== -1;
|
|
var ADDER = IS_MAP ? 'set' : 'add';
|
|
var NativeConstructor = global[CONSTRUCTOR_NAME];
|
|
var NativePrototype = NativeConstructor && NativeConstructor.prototype;
|
|
var Constructor = NativeConstructor;
|
|
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;
|
|
};
|