JintSwitchBlock.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. using System.Collections.Generic;
  2. using Esprima;
  3. using Esprima.Ast;
  4. using Jint.Native;
  5. using Jint.Runtime.Environments;
  6. using Jint.Runtime.Interpreter.Expressions;
  7. namespace Jint.Runtime.Interpreter.Statements
  8. {
  9. internal sealed class JintSwitchBlock
  10. {
  11. private readonly NodeList<SwitchCase> _switchBlock;
  12. private JintSwitchCase[] _jintSwitchBlock;
  13. private bool _initialized;
  14. public JintSwitchBlock(NodeList<SwitchCase> switchBlock)
  15. {
  16. _switchBlock = switchBlock;
  17. }
  18. private void Initialize(EvaluationContext context)
  19. {
  20. var engine = context.Engine;
  21. _jintSwitchBlock = new JintSwitchCase[_switchBlock.Count];
  22. for (var i = 0; i < _jintSwitchBlock.Length; i++)
  23. {
  24. _jintSwitchBlock[i] = new JintSwitchCase(engine, _switchBlock[i]);
  25. }
  26. }
  27. public Completion Execute(EvaluationContext context, JsValue input)
  28. {
  29. if (!_initialized)
  30. {
  31. Initialize(context);
  32. _initialized = true;
  33. }
  34. var engine = context.Engine;
  35. JsValue v = Undefined.Instance;
  36. Location l = context.LastSyntaxNode.Location;
  37. JintSwitchCase defaultCase = null;
  38. bool hit = false;
  39. for (var i = 0; i < (uint) _jintSwitchBlock.Length; i++)
  40. {
  41. var clause = _jintSwitchBlock[i];
  42. EnvironmentRecord oldEnv = null;
  43. if (clause.LexicalDeclarations != null)
  44. {
  45. oldEnv = engine.ExecutionContext.LexicalEnvironment;
  46. var blockEnv = JintEnvironment.NewDeclarativeEnvironment(engine, oldEnv);
  47. JintStatementList.BlockDeclarationInstantiation(engine, blockEnv, clause.LexicalDeclarations);
  48. engine.UpdateLexicalEnvironment(blockEnv);
  49. }
  50. if (clause.Test == null)
  51. {
  52. defaultCase = clause;
  53. }
  54. else
  55. {
  56. var clauseSelector = clause.Test.GetValue(context).Value;
  57. if (clauseSelector == input)
  58. {
  59. hit = true;
  60. }
  61. }
  62. if (hit && clause.Consequent != null)
  63. {
  64. var r = clause.Consequent.Execute(context);
  65. if (oldEnv is not null)
  66. {
  67. engine.UpdateLexicalEnvironment(oldEnv);
  68. }
  69. if (r.Type != CompletionType.Normal)
  70. {
  71. return r;
  72. }
  73. l = r.Location;
  74. v = r.Value ?? Undefined.Instance;
  75. }
  76. }
  77. // do we need to execute the default case ?
  78. if (hit == false && defaultCase != null)
  79. {
  80. EnvironmentRecord oldEnv = null;
  81. if (defaultCase.LexicalDeclarations != null)
  82. {
  83. oldEnv = engine.ExecutionContext.LexicalEnvironment;
  84. var blockEnv = JintEnvironment.NewDeclarativeEnvironment(engine, oldEnv);
  85. JintStatementList.BlockDeclarationInstantiation(engine, blockEnv, defaultCase.LexicalDeclarations);
  86. engine.UpdateLexicalEnvironment(blockEnv);
  87. }
  88. var r = defaultCase.Consequent.Execute(context);
  89. if (oldEnv is not null)
  90. {
  91. engine.UpdateLexicalEnvironment(oldEnv);
  92. }
  93. if (r.Type != CompletionType.Normal)
  94. {
  95. return r;
  96. }
  97. l = r.Location;
  98. v = r.Value ?? Undefined.Instance;
  99. }
  100. return new Completion(CompletionType.Normal, v, null, l);
  101. }
  102. private sealed class JintSwitchCase
  103. {
  104. internal readonly JintStatementList Consequent;
  105. internal readonly JintExpression Test;
  106. internal readonly List<Declaration> LexicalDeclarations;
  107. public JintSwitchCase(Engine engine, SwitchCase switchCase)
  108. {
  109. Consequent = new JintStatementList(null, switchCase.Consequent);
  110. LexicalDeclarations = HoistingScope.GetLexicalDeclarations(switchCase);
  111. if (switchCase.Test != null)
  112. {
  113. Test = JintExpression.Build(engine, switchCase.Test);
  114. }
  115. }
  116. }
  117. }
  118. }