DebugScopes.cs 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. using Jint.Runtime.Environments;
  2. using System.Collections;
  3. using Environment = Jint.Runtime.Environments.Environment;
  4. namespace Jint.Runtime.Debugger
  5. {
  6. public sealed class DebugScopes : IReadOnlyList<DebugScope>
  7. {
  8. private readonly List<DebugScope> _scopes = new();
  9. internal DebugScopes(Environment environment)
  10. {
  11. Populate(environment);
  12. }
  13. public DebugScope this[int index] => _scopes[index];
  14. public int Count => _scopes.Count;
  15. private void Populate(Environment? environment)
  16. {
  17. bool inLocalScope = true;
  18. while (environment is not null)
  19. {
  20. var record = environment;
  21. switch (record)
  22. {
  23. case GlobalEnvironment global:
  24. // Similarly to Chromium, we split the Global environment into Global and Script scopes
  25. AddScope(DebugScopeType.Script, global._declarativeRecord);
  26. AddScope(DebugScopeType.Global, new ObjectEnvironment(environment._engine, global._global, false, false));
  27. break;
  28. case FunctionEnvironment:
  29. AddScope(inLocalScope ? DebugScopeType.Local : DebugScopeType.Closure, record);
  30. // We're now in closure territory
  31. inLocalScope = false;
  32. break;
  33. case ObjectEnvironment:
  34. // If an ObjectEnvironmentRecord is not a GlobalEnvironmentRecord, it's With
  35. AddScope(DebugScopeType.With, record);
  36. break;
  37. case ModuleEnvironment:
  38. AddScope(DebugScopeType.Module, record);
  39. break;
  40. case DeclarativeEnvironment der:
  41. if (der._catchEnvironment)
  42. {
  43. AddScope(DebugScopeType.Catch, record);
  44. }
  45. else
  46. {
  47. bool isTopLevel = environment._outerEnv is FunctionEnvironment;
  48. AddScope(DebugScopeType.Block, record, isTopLevel: isTopLevel);
  49. }
  50. break;
  51. }
  52. environment = environment._outerEnv;
  53. }
  54. }
  55. private void AddScope(DebugScopeType type, Environment record, bool isTopLevel = false)
  56. {
  57. if (record.HasBindings())
  58. {
  59. var scope = new DebugScope(type, record, isTopLevel);
  60. _scopes.Add(scope);
  61. }
  62. }
  63. public IEnumerator<DebugScope> GetEnumerator()
  64. {
  65. return _scopes.GetEnumerator();
  66. }
  67. IEnumerator IEnumerable.GetEnumerator()
  68. {
  69. return _scopes.GetEnumerator();
  70. }
  71. }
  72. }