_collection.js 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. 'use strict';
  2. var global = require('./_global');
  3. var $export = require('./_export');
  4. var redefine = require('./_redefine');
  5. var redefineAll = require('./_redefine-all');
  6. var meta = require('./_meta');
  7. var forOf = require('./_for-of');
  8. var anInstance = require('./_an-instance');
  9. var isObject = require('./_is-object');
  10. var fails = require('./_fails');
  11. var $iterDetect = require('./_iter-detect');
  12. var setToStringTag = require('./_set-to-string-tag');
  13. var inheritIfRequired = require('./_inherit-if-required');
  14. module.exports = function (NAME, wrapper, methods, common, IS_MAP, IS_WEAK) {
  15. var Base = global[NAME];
  16. var C = Base;
  17. var ADDER = IS_MAP ? 'set' : 'add';
  18. var proto = C && C.prototype;
  19. var O = {};
  20. var fixMethod = function (KEY) {
  21. var fn = proto[KEY];
  22. redefine(proto, KEY,
  23. KEY == 'delete' ? function (a) {
  24. return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);
  25. } : KEY == 'has' ? function has(a) {
  26. return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);
  27. } : KEY == 'get' ? function get(a) {
  28. return IS_WEAK && !isObject(a) ? undefined : fn.call(this, a === 0 ? 0 : a);
  29. } : KEY == 'add' ? function add(a) { fn.call(this, a === 0 ? 0 : a); return this; }
  30. : function set(a, b) { fn.call(this, a === 0 ? 0 : a, b); return this; }
  31. );
  32. };
  33. if (typeof C != 'function' || !(IS_WEAK || proto.forEach && !fails(function () {
  34. new C().entries().next();
  35. }))) {
  36. // create collection constructor
  37. C = common.getConstructor(wrapper, NAME, IS_MAP, ADDER);
  38. redefineAll(C.prototype, methods);
  39. meta.NEED = true;
  40. } else {
  41. var instance = new C();
  42. // early implementations not supports chaining
  43. var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) != instance;
  44. // V8 ~ Chromium 40- weak-collections throws on primitives, but should return false
  45. var THROWS_ON_PRIMITIVES = fails(function () { instance.has(1); });
  46. // most early implementations doesn't supports iterables, most modern - not close it correctly
  47. var ACCEPT_ITERABLES = $iterDetect(function (iter) { new C(iter); }); // eslint-disable-line no-new
  48. // for early implementations -0 and +0 not the same
  49. var BUGGY_ZERO = !IS_WEAK && fails(function () {
  50. // V8 ~ Chromium 42- fails only with 5+ elements
  51. var $instance = new C();
  52. var index = 5;
  53. while (index--) $instance[ADDER](index, index);
  54. return !$instance.has(-0);
  55. });
  56. if (!ACCEPT_ITERABLES) {
  57. C = wrapper(function (target, iterable) {
  58. anInstance(target, C, NAME);
  59. var that = inheritIfRequired(new Base(), target, C);
  60. if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);
  61. return that;
  62. });
  63. C.prototype = proto;
  64. proto.constructor = C;
  65. }
  66. if (THROWS_ON_PRIMITIVES || BUGGY_ZERO) {
  67. fixMethod('delete');
  68. fixMethod('has');
  69. IS_MAP && fixMethod('get');
  70. }
  71. if (BUGGY_ZERO || HASNT_CHAINING) fixMethod(ADDER);
  72. // weak collections should not contains .clear method
  73. if (IS_WEAK && proto.clear) delete proto.clear;
  74. }
  75. setToStringTag(C, NAME);
  76. O[NAME] = C;
  77. $export($export.G + $export.W + $export.F * (C != Base), O);
  78. if (!IS_WEAK) common.setStrong(C, NAME, IS_MAP);
  79. return C;
  80. };