$.collection.js 3.0 KB

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