SymbolConstructor.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. using Jint.Collections;
  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. {
  9. /// <summary>
  10. /// 19.4
  11. /// http://www.ecma-international.org/ecma-262/6.0/index.html#sec-symbol-objects
  12. /// </summary>
  13. public sealed class SymbolConstructor : FunctionInstance, IConstructor
  14. {
  15. private static readonly JsString _functionName = new JsString("Symbol");
  16. internal SymbolConstructor(
  17. Engine engine,
  18. Realm realm,
  19. FunctionPrototype functionPrototype,
  20. ObjectPrototype objectPrototype)
  21. : base(engine, realm, _functionName, FunctionThisMode.Global)
  22. {
  23. _prototype = functionPrototype;
  24. PrototypeObject = new SymbolPrototype(engine, realm, this, objectPrototype);
  25. _length = new PropertyDescriptor(JsNumber.PositiveZero, PropertyFlag.Configurable);
  26. _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
  27. }
  28. protected override void Initialize()
  29. {
  30. const PropertyFlag lengthFlags = PropertyFlag.Configurable;
  31. const PropertyFlag propertyFlags = PropertyFlag.AllForbidden;
  32. var properties = new PropertyDictionary(15, checkExistingKeys: false)
  33. {
  34. ["for"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "for", For, 1, lengthFlags), PropertyFlag.Writable | PropertyFlag.Configurable),
  35. ["keyFor"] = new PropertyDescriptor(new ClrFunctionInstance(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. };
  50. SetProperties(properties);
  51. }
  52. /// <summary>
  53. /// http://www.ecma-international.org/ecma-262/6.0/index.html#sec-symbol-description
  54. /// </summary>
  55. public override JsValue Call(JsValue thisObject, JsValue[] arguments)
  56. {
  57. var description = arguments.At(0);
  58. var descString = description.IsUndefined()
  59. ? Undefined
  60. : TypeConverter.ToJsString(description);
  61. var value = _engine.GlobalSymbolRegistry.CreateSymbol(descString);
  62. return value;
  63. }
  64. public JsValue For(JsValue thisObj, JsValue[] arguments)
  65. {
  66. var stringKey = TypeConverter.ToJsString(arguments.At(0));
  67. // 2. ReturnIfAbrupt(stringKey).
  68. if (!_engine.GlobalSymbolRegistry.TryGetSymbol(stringKey, out var symbol))
  69. {
  70. symbol = _engine.GlobalSymbolRegistry.CreateSymbol(stringKey);
  71. _engine.GlobalSymbolRegistry.Add(symbol);
  72. }
  73. return symbol;
  74. }
  75. public JsValue KeyFor(JsValue thisObj, JsValue[] arguments)
  76. {
  77. var symbol = arguments.At(0) as JsSymbol;
  78. if (symbol is null)
  79. {
  80. ExceptionHelper.ThrowTypeError(_realm);
  81. }
  82. if (_engine.GlobalSymbolRegistry.TryGetSymbol(symbol._value, out var e))
  83. {
  84. return e._value;
  85. }
  86. return Undefined;
  87. }
  88. public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
  89. {
  90. ExceptionHelper.ThrowTypeError(_realm);
  91. return null;
  92. }
  93. public SymbolInstance Construct(JsSymbol symbol)
  94. {
  95. var instance = new SymbolInstance(Engine)
  96. {
  97. _prototype = PrototypeObject,
  98. SymbolData = symbol
  99. };
  100. return instance;
  101. }
  102. public SymbolPrototype PrototypeObject { get; private set; }
  103. }
  104. }