collection.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. 'use strict';
  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 defineBuiltIn = require('../internals/define-built-in');
  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 isNullOrUndefined = require('../internals/is-null-or-undefined');
  12. var isObject = require('../internals/is-object');
  13. var fails = require('../internals/fails');
  14. var checkCorrectnessOfIteration = require('../internals/check-correctness-of-iteration');
  15. var setToStringTag = require('../internals/set-to-string-tag');
  16. 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;
  24. var exported = {};
  25. var fixMethod = function (KEY) {
  26. var uncurriedNativeMethod = uncurryThis(NativePrototype[KEY]);
  27. defineBuiltIn(NativePrototype, KEY,
  28. KEY == 'add' ? function add(value) {
  29. uncurriedNativeMethod(this, value === 0 ? 0 : value);
  30. return this;
  31. } : KEY == 'delete' ? function (key) {
  32. return IS_WEAK && !isObject(key) ? false : uncurriedNativeMethod(this, key === 0 ? 0 : key);
  33. } : KEY == 'get' ? function get(key) {
  34. return IS_WEAK && !isObject(key) ? undefined : uncurriedNativeMethod(this, key === 0 ? 0 : key);
  35. } : KEY == 'has' ? function has(key) {
  36. return IS_WEAK && !isObject(key) ? false : uncurriedNativeMethod(this, key === 0 ? 0 : key);
  37. } : function set(key, value) {
  38. uncurriedNativeMethod(this, key === 0 ? 0 : key, value);
  39. return this;
  40. }
  41. );
  42. };
  43. var REPLACE = isForced(
  44. CONSTRUCTOR_NAME,
  45. !isCallable(NativeConstructor) || !(IS_WEAK || NativePrototype.forEach && !fails(function () {
  46. new NativeConstructor().entries().next();
  47. }))
  48. );
  49. if (REPLACE) {
  50. // create collection constructor
  51. Constructor = common.getConstructor(wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER);
  52. InternalMetadataModule.enable();
  53. } else if (isForced(CONSTRUCTOR_NAME, true)) {
  54. var instance = new Constructor();
  55. // early implementations not supports chaining
  56. var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) != instance;
  57. // V8 ~ Chromium 40- weak-collections throws on primitives, but should return false
  58. var THROWS_ON_PRIMITIVES = fails(function () { instance.has(1); });
  59. // most early implementations doesn't supports iterables, most modern - not close it correctly
  60. // eslint-disable-next-line no-new -- required for testing
  61. var ACCEPT_ITERABLES = checkCorrectnessOfIteration(function (iterable) { new NativeConstructor(iterable); });
  62. // for early implementations -0 and +0 not the same
  63. var BUGGY_ZERO = !IS_WEAK && fails(function () {
  64. // V8 ~ Chromium 42- fails only with 5+ elements
  65. var $instance = new NativeConstructor();
  66. var index = 5;
  67. while (index--) $instance[ADDER](index, index);
  68. return !$instance.has(-0);
  69. });
  70. if (!ACCEPT_ITERABLES) {
  71. Constructor = wrapper(function (dummy, iterable) {
  72. anInstance(dummy, NativePrototype);
  73. var that = inheritIfRequired(new NativeConstructor(), dummy, Constructor);
  74. if (!isNullOrUndefined(iterable)) iterate(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });
  75. return that;
  76. });
  77. Constructor.prototype = NativePrototype;
  78. NativePrototype.constructor = Constructor;
  79. }
  80. if (THROWS_ON_PRIMITIVES || BUGGY_ZERO) {
  81. fixMethod('delete');
  82. fixMethod('has');
  83. IS_MAP && fixMethod('get');
  84. }
  85. if (BUGGY_ZERO || HASNT_CHAINING) fixMethod(ADDER);
  86. // weak collections should not contains .clear method
  87. if (IS_WEAK && NativePrototype.clear) delete NativePrototype.clear;
  88. }
  89. exported[CONSTRUCTOR_NAME] = Constructor;
  90. $({ global: true, constructor: true, forced: Constructor != NativeConstructor }, exported);
  91. setToStringTag(Constructor, CONSTRUCTOR_NAME);
  92. if (!IS_WEAK) common.setStrong(Constructor, CONSTRUCTOR_NAME, IS_MAP);
  93. return Constructor;
  94. };