es.symbol.description.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. // `Symbol.prototype.description` getter
  2. // https://tc39.es/ecma262/#sec-symbol.prototype.description
  3. 'use strict';
  4. var $ = require('../internals/export');
  5. var DESCRIPTORS = require('../internals/descriptors');
  6. var globalThis = require('../internals/global-this');
  7. var call = require('../internals/function-call');
  8. var uncurryThis = require('../internals/function-uncurry-this');
  9. var hasOwn = require('../internals/has-own-property');
  10. var isCallable = require('../internals/is-callable');
  11. var isPrototypeOf = require('../internals/object-is-prototype-of');
  12. var toString = require('../internals/to-string');
  13. var defineBuiltInAccessor = require('../internals/define-built-in-accessor');
  14. var copyConstructorProperties = require('../internals/copy-constructor-properties');
  15. var NativeSymbol = globalThis.Symbol;
  16. var SymbolPrototype = NativeSymbol && NativeSymbol.prototype;
  17. if (DESCRIPTORS && isCallable(NativeSymbol) && (!('description' in SymbolPrototype) ||
  18. // Safari 12 bug
  19. NativeSymbol().description !== undefined
  20. )) {
  21. var EmptyStringDescriptionStore = {};
  22. // wrap Symbol constructor for correct work with undefined description
  23. var SymbolWrapper = function Symbol() {
  24. var description = arguments.length < 1 || arguments[0] === undefined ? undefined : toString(arguments[0]);
  25. var result = isPrototypeOf(SymbolPrototype, this)
  26. // eslint-disable-next-line sonarjs/inconsistent-function-call -- ok
  27. ? new NativeSymbol(description)
  28. // in Edge 13, String(Symbol(undefined)) === 'Symbol(undefined)'
  29. : description === undefined ? NativeSymbol() : NativeSymbol(description);
  30. if (description === '') EmptyStringDescriptionStore[result] = true;
  31. return result;
  32. };
  33. copyConstructorProperties(SymbolWrapper, NativeSymbol);
  34. // wrap Symbol.for for correct handling of empty string descriptions
  35. var nativeFor = SymbolWrapper['for'];
  36. SymbolWrapper['for'] = { 'for': function (key) {
  37. var stringKey = toString(key);
  38. var symbol = call(nativeFor, this, stringKey);
  39. if (stringKey === '') EmptyStringDescriptionStore[symbol] = true;
  40. return symbol;
  41. } }['for'];
  42. SymbolWrapper.prototype = SymbolPrototype;
  43. SymbolPrototype.constructor = SymbolWrapper;
  44. var NATIVE_SYMBOL = String(NativeSymbol('description detection')) === 'Symbol(description detection)';
  45. var thisSymbolValue = uncurryThis(SymbolPrototype.valueOf);
  46. var symbolDescriptiveString = uncurryThis(SymbolPrototype.toString);
  47. var regexp = /^Symbol\((.*)\)[^)]+$/;
  48. var replace = uncurryThis(''.replace);
  49. var stringSlice = uncurryThis(''.slice);
  50. defineBuiltInAccessor(SymbolPrototype, 'description', {
  51. configurable: true,
  52. get: function description() {
  53. var symbol = thisSymbolValue(this);
  54. if (hasOwn(EmptyStringDescriptionStore, symbol)) return '';
  55. var string = symbolDescriptiveString(symbol);
  56. var desc = NATIVE_SYMBOL ? stringSlice(string, 7, -1) : replace(string, regexp, '$1');
  57. return desc === '' ? undefined : desc;
  58. }
  59. });
  60. $({ global: true, constructor: true, forced: true }, {
  61. Symbol: SymbolWrapper
  62. });
  63. }