es6.symbol.js 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. 'use strict';
  2. // ECMAScript 6 symbols shim
  3. var global = require('./_global')
  4. , has = require('./_has')
  5. , DESCRIPTORS = require('./_descriptors')
  6. , $export = require('./_export')
  7. , redefine = require('./_redefine')
  8. , META = require('./_meta').KEY
  9. , $fails = require('./_fails')
  10. , shared = require('./_shared')
  11. , setToStringTag = require('./_set-to-string-tag')
  12. , uid = require('./_uid')
  13. , wks = require('./_wks')
  14. , wksExt = require('./_wks-ext')
  15. , wksDefine = require('./_wks-define')
  16. , keyOf = require('./_keyof')
  17. , enumKeys = require('./_enum-keys')
  18. , isArray = require('./_is-array')
  19. , anObject = require('./_an-object')
  20. , toIObject = require('./_to-iobject')
  21. , toPrimitive = require('./_to-primitive')
  22. , createDesc = require('./_property-desc')
  23. , _create = require('./_object-create')
  24. , gOPNExt = require('./_object-gopn-ext')
  25. , $GOPD = require('./_object-gopd')
  26. , $DP = require('./_object-dp')
  27. , $keys = require('./_object-keys')
  28. , gOPD = $GOPD.f
  29. , dP = $DP.f
  30. , gOPN = gOPNExt.f
  31. , $Symbol = global.Symbol
  32. , $JSON = global.JSON
  33. , _stringify = $JSON && $JSON.stringify
  34. , PROTOTYPE = 'prototype'
  35. , HIDDEN = wks('_hidden')
  36. , TO_PRIMITIVE = wks('toPrimitive')
  37. , isEnum = {}.propertyIsEnumerable
  38. , SymbolRegistry = shared('symbol-registry')
  39. , AllSymbols = shared('symbols')
  40. , OPSymbols = shared('op-symbols')
  41. , ObjectProto = Object[PROTOTYPE]
  42. , USE_NATIVE = typeof $Symbol == 'function'
  43. , QObject = global.QObject;
  44. // Don't use setters in Qt Script, https://github.com/zloirock/core-js/issues/173
  45. var setter = !QObject || !QObject[PROTOTYPE] || !QObject[PROTOTYPE].findChild;
  46. // fallback for old Android, https://code.google.com/p/v8/issues/detail?id=687
  47. var setSymbolDesc = DESCRIPTORS && $fails(function(){
  48. return _create(dP({}, 'a', {
  49. get: function(){ return dP(this, 'a', {value: 7}).a; }
  50. })).a != 7;
  51. }) ? function(it, key, D){
  52. var protoDesc = gOPD(ObjectProto, key);
  53. if(protoDesc)delete ObjectProto[key];
  54. dP(it, key, D);
  55. if(protoDesc && it !== ObjectProto)dP(ObjectProto, key, protoDesc);
  56. } : dP;
  57. var wrap = function(tag){
  58. var sym = AllSymbols[tag] = _create($Symbol[PROTOTYPE]);
  59. sym._k = tag;
  60. return sym;
  61. };
  62. var isSymbol = USE_NATIVE && typeof $Symbol.iterator == 'symbol' ? function(it){
  63. return typeof it == 'symbol';
  64. } : function(it){
  65. return it instanceof $Symbol;
  66. };
  67. var $defineProperty = function defineProperty(it, key, D){
  68. if(it === ObjectProto)$defineProperty(OPSymbols, key, D);
  69. anObject(it);
  70. key = toPrimitive(key, true);
  71. anObject(D);
  72. if(has(AllSymbols, key)){
  73. if(!D.enumerable){
  74. if(!has(it, HIDDEN))dP(it, HIDDEN, createDesc(1, {}));
  75. it[HIDDEN][key] = true;
  76. } else {
  77. if(has(it, HIDDEN) && it[HIDDEN][key])it[HIDDEN][key] = false;
  78. D = _create(D, {enumerable: createDesc(0, false)});
  79. } return setSymbolDesc(it, key, D);
  80. } return dP(it, key, D);
  81. };
  82. var $defineProperties = function defineProperties(it, P){
  83. anObject(it);
  84. var keys = enumKeys(P = toIObject(P))
  85. , i = 0
  86. , l = keys.length
  87. , key;
  88. while(l > i)$defineProperty(it, key = keys[i++], P[key]);
  89. return it;
  90. };
  91. var $create = function create(it, P){
  92. return P === undefined ? _create(it) : $defineProperties(_create(it), P);
  93. };
  94. var $propertyIsEnumerable = function propertyIsEnumerable(key){
  95. var E = isEnum.call(this, key = toPrimitive(key, true));
  96. if(this === ObjectProto && has(AllSymbols, key) && !has(OPSymbols, key))return false;
  97. return E || !has(this, key) || !has(AllSymbols, key) || has(this, HIDDEN) && this[HIDDEN][key] ? E : true;
  98. };
  99. var $getOwnPropertyDescriptor = function getOwnPropertyDescriptor(it, key){
  100. it = toIObject(it);
  101. key = toPrimitive(key, true);
  102. if(it === ObjectProto && has(AllSymbols, key) && !has(OPSymbols, key))return;
  103. var D = gOPD(it, key);
  104. if(D && has(AllSymbols, key) && !(has(it, HIDDEN) && it[HIDDEN][key]))D.enumerable = true;
  105. return D;
  106. };
  107. var $getOwnPropertyNames = function getOwnPropertyNames(it){
  108. var names = gOPN(toIObject(it))
  109. , result = []
  110. , i = 0
  111. , key;
  112. while(names.length > i){
  113. if(!has(AllSymbols, key = names[i++]) && key != HIDDEN && key != META)result.push(key);
  114. } return result;
  115. };
  116. var $getOwnPropertySymbols = function getOwnPropertySymbols(it){
  117. var IS_OP = it === ObjectProto
  118. , names = gOPN(IS_OP ? OPSymbols : toIObject(it))
  119. , result = []
  120. , i = 0
  121. , key;
  122. while(names.length > i){
  123. if(has(AllSymbols, key = names[i++]) && (IS_OP ? has(ObjectProto, key) : true))result.push(AllSymbols[key]);
  124. } return result;
  125. };
  126. // 19.4.1.1 Symbol([description])
  127. if(!USE_NATIVE){
  128. $Symbol = function Symbol(){
  129. if(this instanceof $Symbol)throw TypeError('Symbol is not a constructor!');
  130. var tag = uid(arguments.length > 0 ? arguments[0] : undefined);
  131. var $set = function(value){
  132. if(this === ObjectProto)$set.call(OPSymbols, value);
  133. if(has(this, HIDDEN) && has(this[HIDDEN], tag))this[HIDDEN][tag] = false;
  134. setSymbolDesc(this, tag, createDesc(1, value));
  135. };
  136. if(DESCRIPTORS && setter)setSymbolDesc(ObjectProto, tag, {configurable: true, set: $set});
  137. return wrap(tag);
  138. };
  139. redefine($Symbol[PROTOTYPE], 'toString', function toString(){
  140. return this._k;
  141. });
  142. $GOPD.f = $getOwnPropertyDescriptor;
  143. $DP.f = $defineProperty;
  144. require('./_object-gopn').f = gOPNExt.f = $getOwnPropertyNames;
  145. require('./_object-pie').f = $propertyIsEnumerable;
  146. require('./_object-gops').f = $getOwnPropertySymbols;
  147. if(DESCRIPTORS && !require('./_library')){
  148. redefine(ObjectProto, 'propertyIsEnumerable', $propertyIsEnumerable, true);
  149. }
  150. wksExt.f = function(name){
  151. return wrap(wks(name));
  152. }
  153. }
  154. $export($export.G + $export.W + $export.F * !USE_NATIVE, {Symbol: $Symbol});
  155. for(var symbols = (
  156. // 19.4.2.2, 19.4.2.3, 19.4.2.4, 19.4.2.6, 19.4.2.8, 19.4.2.9, 19.4.2.10, 19.4.2.11, 19.4.2.12, 19.4.2.13, 19.4.2.14
  157. 'hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables'
  158. ).split(','), i = 0; symbols.length > i; )wks(symbols[i++]);
  159. for(var symbols = $keys(wks.store), i = 0; symbols.length > i; )wksDefine(symbols[i++]);
  160. $export($export.S + $export.F * !USE_NATIVE, 'Symbol', {
  161. // 19.4.2.1 Symbol.for(key)
  162. 'for': function(key){
  163. return has(SymbolRegistry, key += '')
  164. ? SymbolRegistry[key]
  165. : SymbolRegistry[key] = $Symbol(key);
  166. },
  167. // 19.4.2.5 Symbol.keyFor(sym)
  168. keyFor: function keyFor(key){
  169. if(isSymbol(key))return keyOf(SymbolRegistry, key);
  170. throw TypeError(key + ' is not a symbol!');
  171. },
  172. useSetter: function(){ setter = true; },
  173. useSimple: function(){ setter = false; }
  174. });
  175. $export($export.S + $export.F * !USE_NATIVE, 'Object', {
  176. // 19.1.2.2 Object.create(O [, Properties])
  177. create: $create,
  178. // 19.1.2.4 Object.defineProperty(O, P, Attributes)
  179. defineProperty: $defineProperty,
  180. // 19.1.2.3 Object.defineProperties(O, Properties)
  181. defineProperties: $defineProperties,
  182. // 19.1.2.6 Object.getOwnPropertyDescriptor(O, P)
  183. getOwnPropertyDescriptor: $getOwnPropertyDescriptor,
  184. // 19.1.2.7 Object.getOwnPropertyNames(O)
  185. getOwnPropertyNames: $getOwnPropertyNames,
  186. // 19.1.2.8 Object.getOwnPropertySymbols(O)
  187. getOwnPropertySymbols: $getOwnPropertySymbols
  188. });
  189. // 24.3.2 JSON.stringify(value [, replacer [, space]])
  190. $JSON && $export($export.S + $export.F * (!USE_NATIVE || $fails(function(){
  191. var S = $Symbol();
  192. // MS Edge converts symbol values to JSON as {}
  193. // WebKit converts symbol values to JSON as null
  194. // V8 throws on boxed symbols
  195. return _stringify([S]) != '[null]' || _stringify({a: S}) != '{}' || _stringify(Object(S)) != '{}';
  196. })), 'JSON', {
  197. stringify: function stringify(it){
  198. if(it === undefined || isSymbol(it))return; // IE8 returns string on undefined
  199. var args = [it]
  200. , i = 1
  201. , replacer, $replacer;
  202. while(arguments.length > i)args.push(arguments[i++]);
  203. replacer = args[1];
  204. if(typeof replacer == 'function')$replacer = replacer;
  205. if($replacer || !isArray(replacer))replacer = function(key, value){
  206. if($replacer)value = $replacer.call(this, key, value);
  207. if(!isSymbol(value))return value;
  208. };
  209. args[1] = replacer;
  210. return _stringify.apply($JSON, args);
  211. }
  212. });
  213. // 19.4.3.4 Symbol.prototype[@@toPrimitive](hint)
  214. $Symbol[PROTOTYPE][TO_PRIMITIVE] || require('./_hide')($Symbol[PROTOTYPE], TO_PRIMITIVE, $Symbol[PROTOTYPE].valueOf);
  215. // 19.4.3.5 Symbol.prototype[@@toStringTag]
  216. setToStringTag($Symbol, 'Symbol');
  217. // 20.2.1.9 Math[@@toStringTag]
  218. setToStringTag(Math, 'Math', true);
  219. // 24.3.3 JSON[@@toStringTag]
  220. setToStringTag(global.JSON, 'JSON', true);