SymbolConstructor.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. #pragma warning disable CA1859 // Use concrete types when possible for improved performance -- most of constructor methods return JsValue
  2. using Jint.Native.Function;
  3. using Jint.Native.Object;
  4. using Jint.Runtime;
  5. using Jint.Runtime.Descriptors;
  6. using Jint.Runtime.Interop;
  7. namespace Jint.Native.Symbol;
  8. /// <summary>
  9. /// 19.4
  10. /// http://www.ecma-international.org/ecma-262/6.0/index.html#sec-symbol-objects
  11. /// </summary>
  12. internal sealed class SymbolConstructor : Constructor
  13. {
  14. private static readonly JsString _functionName = new JsString("Symbol");
  15. internal SymbolConstructor(
  16. Engine engine,
  17. Realm realm,
  18. FunctionPrototype functionPrototype,
  19. ObjectPrototype objectPrototype)
  20. : base(engine, realm, _functionName)
  21. {
  22. _prototype = functionPrototype;
  23. PrototypeObject = new SymbolPrototype(engine, realm, this, objectPrototype);
  24. _length = new PropertyDescriptor(JsNumber.PositiveZero, PropertyFlag.Configurable);
  25. _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
  26. }
  27. public SymbolPrototype PrototypeObject { get; }
  28. protected override void Initialize()
  29. {
  30. const PropertyFlag lengthFlags = PropertyFlag.Configurable;
  31. const PropertyFlag propertyFlags = PropertyFlag.AllForbidden;
  32. var properties = new PropertyDictionary(17, checkExistingKeys: false)
  33. {
  34. ["for"] = new PropertyDescriptor(new ClrFunction(Engine, "for", For, 1, lengthFlags), PropertyFlag.Writable | PropertyFlag.Configurable),
  35. ["keyFor"] = new PropertyDescriptor(new ClrFunction(Engine, "keyFor", KeyFor, 1, lengthFlags), PropertyFlag.Writable | PropertyFlag.Configurable),
  36. ["hasInstance"] = new PropertyDescriptor(GlobalSymbolRegistry.HasInstance, propertyFlags),
  37. ["isConcatSpreadable"] = new PropertyDescriptor(GlobalSymbolRegistry.IsConcatSpreadable, propertyFlags),
  38. ["iterator"] = new PropertyDescriptor(GlobalSymbolRegistry.Iterator, propertyFlags),
  39. ["match"] = new PropertyDescriptor(GlobalSymbolRegistry.Match, propertyFlags),
  40. ["matchAll"] = new PropertyDescriptor(GlobalSymbolRegistry.MatchAll, propertyFlags),
  41. ["replace"] = new PropertyDescriptor(GlobalSymbolRegistry.Replace, propertyFlags),
  42. ["search"] = new PropertyDescriptor(GlobalSymbolRegistry.Search, propertyFlags),
  43. ["species"] = new PropertyDescriptor(GlobalSymbolRegistry.Species, propertyFlags),
  44. ["split"] = new PropertyDescriptor(GlobalSymbolRegistry.Split, propertyFlags),
  45. ["toPrimitive"] = new PropertyDescriptor(GlobalSymbolRegistry.ToPrimitive, propertyFlags),
  46. ["toStringTag"] = new PropertyDescriptor(GlobalSymbolRegistry.ToStringTag, propertyFlags),
  47. ["unscopables"] = new PropertyDescriptor(GlobalSymbolRegistry.Unscopables, propertyFlags),
  48. ["asyncIterator"] = new PropertyDescriptor(GlobalSymbolRegistry.AsyncIterator, propertyFlags),
  49. ["dispose"] = new PropertyDescriptor(GlobalSymbolRegistry.Dispose, propertyFlags),
  50. ["asyncDispose"] = new PropertyDescriptor(GlobalSymbolRegistry.AsyncDispose, propertyFlags),
  51. };
  52. SetProperties(properties);
  53. }
  54. /// <summary>
  55. /// http://www.ecma-international.org/ecma-262/6.0/index.html#sec-symbol-description
  56. /// </summary>
  57. protected internal override JsValue Call(JsValue thisObject, JsCallArguments arguments)
  58. {
  59. var description = arguments.At(0);
  60. var descString = description.IsUndefined()
  61. ? Undefined
  62. : TypeConverter.ToJsString(description);
  63. var value = GlobalSymbolRegistry.CreateSymbol(descString);
  64. return value;
  65. }
  66. /// <summary>
  67. /// https://tc39.es/ecma262/#sec-symbol.for
  68. /// </summary>
  69. private JsValue For(JsValue thisObject, JsCallArguments arguments)
  70. {
  71. var stringKey = TypeConverter.ToJsString(arguments.At(0));
  72. // 2. ReturnIfAbrupt(stringKey).
  73. if (!_engine.GlobalSymbolRegistry.TryGetSymbol(stringKey, out var symbol))
  74. {
  75. symbol = GlobalSymbolRegistry.CreateSymbol(stringKey);
  76. _engine.GlobalSymbolRegistry.Add(symbol);
  77. }
  78. return symbol;
  79. }
  80. /// <summary>
  81. /// https://tc39.es/ecma262/#sec-symbol.keyfor
  82. /// </summary>
  83. private JsValue KeyFor(JsValue thisObject, JsCallArguments arguments)
  84. {
  85. var symbol = arguments.At(0) as JsSymbol;
  86. if (symbol is null)
  87. {
  88. Throw.TypeError(_realm);
  89. }
  90. if (_engine.GlobalSymbolRegistry.TryGetSymbol(symbol._value, out var e))
  91. {
  92. return e._value;
  93. }
  94. return Undefined;
  95. }
  96. public override ObjectInstance Construct(JsCallArguments arguments, JsValue newTarget)
  97. {
  98. Throw.TypeError(_realm, "Symbol is not a constructor");
  99. return null;
  100. }
  101. public SymbolInstance Construct(JsSymbol symbol)
  102. {
  103. return new SymbolInstance(Engine, PrototypeObject, symbol);
  104. }
  105. }