es6.symbol.js 9.1 KB

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