SetPrototype.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. #pragma warning disable CA1859 // Use concrete types when possible for improved performance -- most of prototype methods return JsValue
  2. using Jint.Collections;
  3. using Jint.Native.Object;
  4. using Jint.Native.Symbol;
  5. using Jint.Runtime;
  6. using Jint.Runtime.Descriptors;
  7. using Jint.Runtime.Interop;
  8. namespace Jint.Native.Set;
  9. /// <summary>
  10. /// https://www.ecma-international.org/ecma-262/6.0/#sec-set-objects
  11. /// </summary>
  12. internal sealed class SetPrototype : Prototype
  13. {
  14. private readonly SetConstructor _constructor;
  15. internal SetPrototype(
  16. Engine engine,
  17. Realm realm,
  18. SetConstructor setConstructor,
  19. ObjectPrototype objectPrototype) : base(engine, realm)
  20. {
  21. _prototype = objectPrototype;
  22. _constructor = setConstructor;
  23. }
  24. protected override void Initialize()
  25. {
  26. var properties = new PropertyDictionary(12, checkExistingKeys: false)
  27. {
  28. ["length"] = new PropertyDescriptor(0, PropertyFlag.Configurable),
  29. ["constructor"] = new PropertyDescriptor(_constructor, PropertyFlag.NonEnumerable),
  30. ["add"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "add", Add, 1, PropertyFlag.Configurable), true, false, true),
  31. ["clear"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "clear", Clear, 0, PropertyFlag.Configurable), true, false, true),
  32. ["delete"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "delete", Delete, 1, PropertyFlag.Configurable), true, false, true),
  33. ["entries"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "entries", Entries, 0, PropertyFlag.Configurable), true, false, true),
  34. ["forEach"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "forEach", ForEach, 1, PropertyFlag.Configurable), true, false, true),
  35. ["has"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "has", Has, 1, PropertyFlag.Configurable), true, false, true),
  36. ["keys"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "keys", Values, 0, PropertyFlag.Configurable), true, false, true),
  37. ["values"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "values", Values, 0, PropertyFlag.Configurable), true, false, true),
  38. ["size"] = new GetSetPropertyDescriptor(get: new ClrFunctionInstance(Engine, "get size", Size, 0, PropertyFlag.Configurable), set: null, PropertyFlag.Configurable)
  39. };
  40. SetProperties(properties);
  41. var symbols = new SymbolDictionary(2)
  42. {
  43. [GlobalSymbolRegistry.Iterator] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "iterator", Values, 1, PropertyFlag.Configurable), true, false, true),
  44. [GlobalSymbolRegistry.ToStringTag] = new PropertyDescriptor("Set", false, false, true)
  45. };
  46. SetSymbols(symbols);
  47. }
  48. private JsValue Size(JsValue thisObject, JsValue[] arguments)
  49. {
  50. AssertSetInstance(thisObject);
  51. return JsNumber.Create(0);
  52. }
  53. private JsValue Add(JsValue thisObject, JsValue[] arguments)
  54. {
  55. var set = AssertSetInstance(thisObject);
  56. var value = arguments.At(0);
  57. if (value is JsNumber number && number.IsNegativeZero())
  58. {
  59. value = JsNumber.PositiveZero;
  60. }
  61. set.Add(value);
  62. return thisObject;
  63. }
  64. private JsValue Clear(JsValue thisObject, JsValue[] arguments)
  65. {
  66. var set = AssertSetInstance(thisObject);
  67. set.Clear();
  68. return Undefined;
  69. }
  70. private JsValue Delete(JsValue thisObject, JsValue[] arguments)
  71. {
  72. var set = AssertSetInstance(thisObject);
  73. return set.SetDelete(arguments.At(0))
  74. ? JsBoolean.True
  75. : JsBoolean.False;
  76. }
  77. private JsValue Has(JsValue thisObject, JsValue[] arguments)
  78. {
  79. var set = AssertSetInstance(thisObject);
  80. return set.Has(arguments.At(0))
  81. ? JsBoolean.True
  82. : JsBoolean.False;
  83. }
  84. private JsValue Entries(JsValue thisObject, JsValue[] arguments)
  85. {
  86. var set = AssertSetInstance(thisObject);
  87. return set.Entries();
  88. }
  89. private JsValue ForEach(JsValue thisObject, JsValue[] arguments)
  90. {
  91. var callbackfn = arguments.At(0);
  92. var thisArg = arguments.At(1);
  93. var set = AssertSetInstance(thisObject);
  94. var callable = GetCallable(callbackfn);
  95. set.ForEach(callable, thisArg);
  96. return Undefined;
  97. }
  98. private ObjectInstance Values(JsValue thisObject, JsValue[] arguments)
  99. {
  100. var set = AssertSetInstance(thisObject);
  101. return set.Values();
  102. }
  103. private JsSet AssertSetInstance(JsValue thisObject)
  104. {
  105. if (thisObject is JsSet set)
  106. {
  107. return set;
  108. }
  109. ExceptionHelper.ThrowTypeError(_realm, "object must be a Set");
  110. return default;
  111. }
  112. }