SymbolPrototype.cs 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. #pragma warning disable CA1859 // Use concrete types when possible for improved performance -- most of prototype methods return JsValue
  2. using Jint.Native.Object;
  3. using Jint.Runtime;
  4. using Jint.Runtime.Descriptors;
  5. using Jint.Runtime.Interop;
  6. namespace Jint.Native.Symbol;
  7. /// <summary>
  8. /// https://tc39.es/ecma262/#sec-properties-of-the-symbol-prototype-object
  9. /// </summary>
  10. internal sealed class SymbolPrototype : Prototype
  11. {
  12. private readonly SymbolConstructor _constructor;
  13. internal SymbolPrototype(
  14. Engine engine,
  15. Realm realm,
  16. SymbolConstructor symbolConstructor,
  17. ObjectPrototype objectPrototype)
  18. : base(engine, realm)
  19. {
  20. _prototype = objectPrototype;
  21. _constructor = symbolConstructor;
  22. }
  23. protected override void Initialize()
  24. {
  25. const PropertyFlag lengthFlags = PropertyFlag.Configurable;
  26. const PropertyFlag propertyFlags = PropertyFlag.Configurable;
  27. SetProperties(new PropertyDictionary(5, checkExistingKeys: false)
  28. {
  29. ["length"] = new PropertyDescriptor(JsNumber.PositiveZero, propertyFlags),
  30. ["constructor"] = new PropertyDescriptor(_constructor, PropertyFlag.Configurable | PropertyFlag.Writable),
  31. ["description"] = new GetSetPropertyDescriptor(new ClrFunction(Engine, "description", Description, 0, lengthFlags), Undefined, propertyFlags),
  32. ["toString"] = new PropertyDescriptor(new ClrFunction(Engine, "toString", ToSymbolString, 0, lengthFlags), PropertyFlag.Configurable | PropertyFlag.Writable),
  33. ["valueOf"] = new PropertyDescriptor(new ClrFunction(Engine, "valueOf", ValueOf, 0, lengthFlags), PropertyFlag.Configurable | PropertyFlag.Writable)
  34. });
  35. SetSymbols(new SymbolDictionary(1)
  36. {
  37. [GlobalSymbolRegistry.ToPrimitive] = new PropertyDescriptor(new ClrFunction(Engine, "[Symbol.toPrimitive]", ToPrimitive, 1, lengthFlags), propertyFlags), [GlobalSymbolRegistry.ToStringTag] = new PropertyDescriptor(new JsString("Symbol"), propertyFlags)
  38. }
  39. );
  40. }
  41. /// <summary>
  42. /// https://tc39.es/ecma262/#sec-symbol.prototype.description
  43. /// </summary>
  44. private JsValue Description(JsValue thisObject, JsCallArguments arguments)
  45. {
  46. var sym = ThisSymbolValue(thisObject);
  47. return sym._value;
  48. }
  49. /// <summary>
  50. /// https://tc39.es/ecma262/#sec-symbol.prototype.tostring
  51. /// </summary>
  52. private JsValue ToSymbolString(JsValue thisObject, JsCallArguments arguments)
  53. {
  54. var sym = ThisSymbolValue(thisObject);
  55. return new JsString(sym.ToString());
  56. }
  57. /// <summary>
  58. /// https://tc39.es/ecma262/#sec-symbol.prototype.valueof
  59. /// </summary>
  60. private JsValue ValueOf(JsValue thisObject, JsCallArguments arguments)
  61. {
  62. return ThisSymbolValue(thisObject);
  63. }
  64. /// <summary>
  65. /// https://tc39.es/ecma262/#sec-symbol.prototype-@@toprimitive
  66. /// </summary>
  67. private JsValue ToPrimitive(JsValue thisObject, JsCallArguments arguments)
  68. {
  69. return ThisSymbolValue(thisObject);
  70. }
  71. private JsSymbol ThisSymbolValue(JsValue thisObject)
  72. {
  73. if (thisObject is JsSymbol s)
  74. {
  75. return s;
  76. }
  77. if (thisObject is SymbolInstance instance)
  78. {
  79. return instance.SymbolData;
  80. }
  81. ExceptionHelper.ThrowTypeError(_realm);
  82. return null;
  83. }
  84. }