JsMap.cs 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. using System.Collections;
  2. using System.Diagnostics.CodeAnalysis;
  3. using Jint.Native.Object;
  4. using Jint.Runtime;
  5. using Jint.Runtime.Descriptors;
  6. namespace Jint.Native;
  7. public sealed class JsMap : ObjectInstance, IEnumerable<KeyValuePair<JsValue, JsValue>>
  8. {
  9. private readonly Realm _realm;
  10. internal readonly OrderedDictionary<JsValue, JsValue> _map;
  11. public JsMap(Engine engine, Realm realm) : base(engine)
  12. {
  13. _realm = realm;
  14. _map = new OrderedDictionary<JsValue, JsValue>(SameValueZeroComparer.Instance);
  15. }
  16. public override PropertyDescriptor GetOwnProperty(JsValue property)
  17. {
  18. if (CommonProperties.Size.Equals(property))
  19. {
  20. return new PropertyDescriptor(_map.Count, PropertyFlag.AllForbidden);
  21. }
  22. return base.GetOwnProperty(property);
  23. }
  24. protected override bool TryGetProperty(JsValue property, [NotNullWhen(true)] out PropertyDescriptor? descriptor)
  25. {
  26. if (CommonProperties.Size.Equals(property))
  27. {
  28. descriptor = new PropertyDescriptor(_map.Count, PropertyFlag.AllForbidden);
  29. return true;
  30. }
  31. return base.TryGetProperty(property, out descriptor);
  32. }
  33. public int Size => _map.Count;
  34. public void Clear() => _map.Clear();
  35. public bool Has(JsValue key) => _map.ContainsKey(key);
  36. public bool Remove(JsValue key) => _map.Remove(key);
  37. public new JsValue Get(JsValue key)
  38. {
  39. if (!_map.TryGetValue(key, out var value))
  40. {
  41. return Undefined;
  42. }
  43. return value;
  44. }
  45. public new void Set(JsValue key, JsValue value)
  46. {
  47. if (key is JsNumber number && number.IsNegativeZero())
  48. {
  49. key = JsNumber.PositiveZero;
  50. }
  51. _map[key] = value;
  52. }
  53. internal void ForEach(ICallable callable, JsValue thisArg)
  54. {
  55. var args = _engine._jsValueArrayPool.RentArray(3);
  56. args[2] = this;
  57. for (var i = 0; i < _map.Count; i++)
  58. {
  59. args[0] = _map[i];
  60. args[1] = _map.GetKey(i);
  61. callable.Call(thisArg, args);
  62. }
  63. _engine._jsValueArrayPool.ReturnArray(args);
  64. }
  65. internal ObjectInstance Iterator() => _realm.Intrinsics.MapIteratorPrototype.ConstructEntryIterator(this);
  66. internal ObjectInstance Keys() => _realm.Intrinsics.MapIteratorPrototype.ConstructKeyIterator(this);
  67. internal ObjectInstance Values() => _realm.Intrinsics.MapIteratorPrototype.ConstructValueIterator(this);
  68. public IEnumerator<KeyValuePair<JsValue, JsValue>> GetEnumerator() => _map.GetEnumerator();
  69. IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
  70. }