JintStatement.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. using System.Runtime.CompilerServices;
  2. using Esprima;
  3. using Esprima.Ast;
  4. using Jint.Runtime.Interpreter.Expressions;
  5. namespace Jint.Runtime.Interpreter.Statements
  6. {
  7. internal abstract class JintStatement<T> : JintStatement where T : Statement
  8. {
  9. internal readonly T _statement;
  10. protected JintStatement(Engine engine, T statement) : base(engine, statement)
  11. {
  12. _statement = statement;
  13. }
  14. }
  15. internal abstract class JintStatement
  16. {
  17. protected readonly Engine _engine;
  18. private readonly Statement _statement;
  19. // require sub-classes to set to false explicitly to skip virtual call
  20. protected bool _initialized = true;
  21. protected JintStatement(Engine engine, Statement statement)
  22. {
  23. _engine = engine;
  24. _statement = statement;
  25. }
  26. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  27. public Completion Execute()
  28. {
  29. if (_statement.Type != Nodes.BlockStatement)
  30. {
  31. _engine._lastSyntaxNode = _statement;
  32. _engine.RunBeforeExecuteStatementChecks(_statement);
  33. }
  34. if (!_initialized)
  35. {
  36. Initialize();
  37. _initialized = true;
  38. }
  39. return ExecuteInternal();
  40. }
  41. protected abstract Completion ExecuteInternal();
  42. public Location Location => _statement.Location;
  43. /// <summary>
  44. /// Opportunity to build one-time structures and caching based on lexical context.
  45. /// </summary>
  46. protected virtual void Initialize()
  47. {
  48. }
  49. protected internal static JintStatement Build(Engine engine, Statement statement)
  50. {
  51. return statement.Type switch
  52. {
  53. Nodes.BlockStatement => new JintBlockStatement(engine, (BlockStatement) statement),
  54. Nodes.ReturnStatement => new JintReturnStatement(engine, (ReturnStatement) statement),
  55. Nodes.VariableDeclaration => new JintVariableDeclaration(engine, (VariableDeclaration) statement),
  56. Nodes.BreakStatement => new JintBreakStatement(engine, (BreakStatement) statement),
  57. Nodes.ContinueStatement => new JintContinueStatement(engine, (ContinueStatement) statement),
  58. Nodes.DoWhileStatement => new JintDoWhileStatement(engine, (DoWhileStatement) statement),
  59. Nodes.EmptyStatement => new JintEmptyStatement(engine, (EmptyStatement) statement),
  60. Nodes.ExpressionStatement => new JintExpressionStatement(engine, (ExpressionStatement) statement),
  61. Nodes.ForStatement => new JintForStatement(engine, (ForStatement) statement),
  62. Nodes.ForInStatement => new JintForInForOfStatement(engine, (ForInStatement) statement),
  63. Nodes.ForOfStatement => new JintForInForOfStatement(engine, (ForOfStatement) statement),
  64. Nodes.IfStatement => new JintIfStatement(engine, (IfStatement) statement),
  65. Nodes.LabeledStatement => new JintLabeledStatement(engine, (LabeledStatement) statement),
  66. Nodes.SwitchStatement => new JintSwitchStatement(engine, (SwitchStatement) statement),
  67. Nodes.FunctionDeclaration => new JintFunctionDeclarationStatement(engine, (FunctionDeclaration) statement),
  68. Nodes.ThrowStatement => new JintThrowStatement(engine, (ThrowStatement) statement),
  69. Nodes.TryStatement => new JintTryStatement(engine, (TryStatement) statement),
  70. Nodes.WhileStatement => new JintWhileStatement(engine, (WhileStatement) statement),
  71. Nodes.WithStatement => new JintWithStatement(engine, (WithStatement) statement),
  72. Nodes.DebuggerStatement => new JintDebuggerStatement(engine, (DebuggerStatement) statement),
  73. Nodes.Program => new JintScript(engine, statement as Script ?? ExceptionHelper.ThrowArgumentException<Script>("modules not supported")),
  74. _ => ExceptionHelper.ThrowArgumentOutOfRangeException<JintStatement>(nameof(statement.Type), $"unsupported statement type '{statement.Type}'")
  75. };
  76. }
  77. internal static Completion? FastResolve(StatementListItem statement)
  78. {
  79. if (statement is ReturnStatement rs && rs.Argument is Literal l)
  80. {
  81. var jsValue = JintLiteralExpression.ConvertToJsValue(l);
  82. if (jsValue != null)
  83. {
  84. return new Completion(CompletionType.Return, jsValue, null, rs.Location);
  85. }
  86. }
  87. return null;
  88. }
  89. }
  90. }