BreakPointCollection.cs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. namespace Jint.Runtime.Debugger
  5. {
  6. /// <summary>
  7. /// Collection of breakpoints.
  8. /// </summary>
  9. /// <remarks>
  10. /// Only allows a single breakpoint at the same location (source, column and line).
  11. /// Adding a new breakpoint at the same location <i>replaces</i> the old one - this allows replacing e.g. a
  12. /// conditional breakpoint with a new condition (or remove the condition).
  13. /// </remarks>
  14. public sealed class BreakPointCollection : IEnumerable<BreakPoint>
  15. {
  16. private readonly Dictionary<BreakLocation, BreakPoint> _breakPoints = new(new OptionalSourceBreakLocationEqualityComparer());
  17. public BreakPointCollection()
  18. {
  19. }
  20. /// <summary>
  21. /// Gets or sets whether breakpoints are activated. When false, all breakpoints will fail to match (and be skipped by the debugger).
  22. /// </summary>
  23. public bool Active { get; set; } = true;
  24. public int Count => _breakPoints.Count;
  25. public bool IsReadOnly => false;
  26. /// <summary>
  27. /// Sets a new breakpoint. Note that this will replace any breakpoint at the same location (source/column/line).
  28. /// </summary>
  29. public void Set(BreakPoint breakPoint)
  30. {
  31. _breakPoints[breakPoint.Location] = breakPoint;
  32. }
  33. /// <summary>
  34. /// Removes breakpoint with the given location (source/column/line).
  35. /// Note that a null source matches <i>any</i> source.
  36. /// </summary>
  37. public bool RemoveAt(BreakLocation location)
  38. {
  39. return _breakPoints.Remove(location);
  40. }
  41. /// <summary>
  42. /// Checks whether collection contains a breakpoint at the given location (source/column/line).
  43. /// Note that a null source matches <i>any</i> source.
  44. /// </summary>
  45. public bool Contains(BreakLocation location)
  46. {
  47. return _breakPoints.ContainsKey(location);
  48. }
  49. /// <summary>
  50. /// Removes all breakpoints.
  51. /// </summary>
  52. public void Clear()
  53. {
  54. _breakPoints.Clear();
  55. }
  56. internal BreakPoint FindMatch(DebugHandler debugger, BreakLocation location)
  57. {
  58. if (!Active)
  59. {
  60. return null;
  61. }
  62. if (!_breakPoints.TryGetValue(location, out var breakPoint))
  63. {
  64. return null;
  65. }
  66. if (!string.IsNullOrEmpty(breakPoint.Condition))
  67. {
  68. try
  69. {
  70. var completionValue = debugger.Evaluate(breakPoint.Condition);
  71. // Truthiness check:
  72. if (!TypeConverter.ToBoolean(completionValue))
  73. {
  74. return null;
  75. }
  76. }
  77. catch (Exception ex) when (ex is JavaScriptException || ex is DebugEvaluationException)
  78. {
  79. // Error in the condition means it doesn't match - shouldn't actually throw.
  80. return null;
  81. }
  82. }
  83. return breakPoint;
  84. }
  85. public IEnumerator<BreakPoint> GetEnumerator()
  86. {
  87. return _breakPoints.Values.GetEnumerator();
  88. }
  89. IEnumerator IEnumerable.GetEnumerator()
  90. {
  91. return _breakPoints.GetEnumerator();
  92. }
  93. }
  94. }