es6.symbol.js 7.5 KB

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