WeakMapPrototype.cs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  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.Native.Symbol;
  4. using Jint.Runtime;
  5. using Jint.Runtime.Descriptors;
  6. using Jint.Runtime.Interop;
  7. namespace Jint.Native.WeakMap;
  8. /// <summary>
  9. /// https://tc39.es/ecma262/#sec-weakmap-objects
  10. /// </summary>
  11. internal sealed class WeakMapPrototype : Prototype
  12. {
  13. private readonly WeakMapConstructor _constructor;
  14. internal WeakMapPrototype(
  15. Engine engine,
  16. Realm realm,
  17. WeakMapConstructor constructor,
  18. ObjectPrototype prototype) : base(engine, realm)
  19. {
  20. _prototype = prototype;
  21. _constructor = constructor;
  22. }
  23. protected override void Initialize()
  24. {
  25. const PropertyFlag PropertyFlags = PropertyFlag.Configurable | PropertyFlag.Writable;
  26. var properties = new PropertyDictionary(8, checkExistingKeys: false)
  27. {
  28. ["length"] = new PropertyDescriptor(0, PropertyFlag.Configurable),
  29. ["constructor"] = new PropertyDescriptor(_constructor, PropertyFlag.NonEnumerable),
  30. ["delete"] = new PropertyDescriptor(new ClrFunction(Engine, "delete", Delete, 1, PropertyFlag.Configurable), PropertyFlags),
  31. ["get"] = new PropertyDescriptor(new ClrFunction(Engine, "get", Get, 1, PropertyFlag.Configurable), PropertyFlags),
  32. ["getOrInsert"] = new PropertyDescriptor(new ClrFunction(Engine, "getOrInsert", GetOrInsert, 2, PropertyFlag.Configurable), PropertyFlags),
  33. ["getOrInsertComputed"] = new PropertyDescriptor(new ClrFunction(Engine, "getOrInsertComputed", GetOrInsertComputed, 2, PropertyFlag.Configurable), PropertyFlags),
  34. ["has"] = new PropertyDescriptor(new ClrFunction(Engine, "has", Has, 1, PropertyFlag.Configurable), PropertyFlags),
  35. ["set"] = new PropertyDescriptor(new ClrFunction(Engine, "set", Set, 2, PropertyFlag.Configurable), PropertyFlags),
  36. };
  37. SetProperties(properties);
  38. var symbols = new SymbolDictionary(1)
  39. {
  40. [GlobalSymbolRegistry.ToStringTag] = new PropertyDescriptor("WeakMap", false, false, true)
  41. };
  42. SetSymbols(symbols);
  43. }
  44. private JsValue Get(JsValue thisObject, JsCallArguments arguments)
  45. {
  46. var map = AssertWeakMapInstance(thisObject);
  47. return map.WeakMapGet(arguments.At(0));
  48. }
  49. private JsValue GetOrInsert(JsValue thisObject, JsCallArguments arguments)
  50. {
  51. var map = AssertWeakMapInstance(thisObject);
  52. var key = AssertCanBeHeldWeakly(arguments.At(0));
  53. var value = arguments.At(1);
  54. return map.GetOrInsert(key, value);
  55. }
  56. private JsValue GetOrInsertComputed(JsValue thisObject, JsCallArguments arguments)
  57. {
  58. var map = AssertWeakMapInstance(thisObject);
  59. var key = AssertCanBeHeldWeakly(arguments.At(0));
  60. var callbackfn = arguments.At(1).GetCallable(_realm);
  61. return map.GetOrInsertComputed(key, callbackfn);
  62. }
  63. private JsValue AssertCanBeHeldWeakly(JsValue key)
  64. {
  65. if (!key.CanBeHeldWeakly(_engine.GlobalSymbolRegistry))
  66. {
  67. Throw.TypeError(_realm);
  68. }
  69. return key;
  70. }
  71. private JsValue Delete(JsValue thisObject, JsCallArguments arguments)
  72. {
  73. var map = AssertWeakMapInstance(thisObject);
  74. return arguments.Length > 0 && map.WeakMapDelete(arguments.At(0)) ? JsBoolean.True : JsBoolean.False;
  75. }
  76. private JsValue Set(JsValue thisObject, JsCallArguments arguments)
  77. {
  78. var map = AssertWeakMapInstance(thisObject);
  79. map.WeakMapSet(arguments.At(0), arguments.At(1));
  80. return thisObject;
  81. }
  82. private JsValue Has(JsValue thisObject, JsCallArguments arguments)
  83. {
  84. var map = AssertWeakMapInstance(thisObject);
  85. return map.WeakMapHas(arguments.At(0)) ? JsBoolean.True : JsBoolean.False;
  86. }
  87. private JsWeakMap AssertWeakMapInstance(JsValue thisObject)
  88. {
  89. if (thisObject is JsWeakMap map)
  90. {
  91. return map;
  92. }
  93. Throw.TypeError(_realm, "object must be a WeakMap");
  94. return default;
  95. }
  96. }