DebugScopes.cs 2.6 KB

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