JintVariableDeclaration.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. using Esprima.Ast;
  2. using Jint.Native;
  3. using Jint.Native.Function;
  4. using Jint.Runtime.Interpreter.Expressions;
  5. using Jint.Runtime.References;
  6. namespace Jint.Runtime.Interpreter.Statements
  7. {
  8. internal sealed class JintVariableDeclaration : JintStatement<VariableDeclaration>
  9. {
  10. private static readonly Completion VoidCompletion = new(CompletionType.Normal, null!, default);
  11. private ResolvedDeclaration[] _declarations = Array.Empty<ResolvedDeclaration>();
  12. private sealed class ResolvedDeclaration
  13. {
  14. internal JintExpression? Left;
  15. internal BindingPattern? LeftPattern;
  16. internal JintExpression? Init;
  17. internal JintIdentifierExpression? LeftIdentifierExpression;
  18. internal bool EvalOrArguments;
  19. }
  20. public JintVariableDeclaration(VariableDeclaration statement) : base(statement)
  21. {
  22. }
  23. protected override void Initialize(EvaluationContext context)
  24. {
  25. var engine = context.Engine;
  26. _declarations = new ResolvedDeclaration[_statement.Declarations.Count];
  27. for (var i = 0; i < _declarations.Length; i++)
  28. {
  29. var declaration = _statement.Declarations[i];
  30. JintExpression? left = null;
  31. JintExpression? init = null;
  32. BindingPattern? bindingPattern = null;
  33. if (declaration.Id is BindingPattern bp)
  34. {
  35. bindingPattern = bp;
  36. }
  37. else
  38. {
  39. left = JintExpression.Build(engine, (Identifier) declaration.Id);
  40. }
  41. if (declaration.Init != null)
  42. {
  43. init = JintExpression.Build(engine, declaration.Init);
  44. }
  45. var leftIdentifier = left as JintIdentifierExpression;
  46. _declarations[i] = new ResolvedDeclaration
  47. {
  48. Left = left,
  49. LeftPattern = bindingPattern,
  50. LeftIdentifierExpression = leftIdentifier,
  51. EvalOrArguments = leftIdentifier?.HasEvalOrArguments == true,
  52. Init = init
  53. };
  54. }
  55. }
  56. protected override Completion ExecuteInternal(EvaluationContext context)
  57. {
  58. var engine = context.Engine;
  59. foreach (var declaration in _declarations)
  60. {
  61. if (_statement.Kind != VariableDeclarationKind.Var && declaration.Left != null)
  62. {
  63. var lhs = (Reference) declaration.Left.Evaluate(context).Value;
  64. var value = JsValue.Undefined;
  65. if (declaration.Init != null)
  66. {
  67. var completion = declaration.Init.GetValue(context);
  68. value = completion.Value.Clone();
  69. if (declaration.Init._expression.IsFunctionDefinition())
  70. {
  71. ((FunctionInstance) value).SetFunctionName(lhs.GetReferencedName());
  72. }
  73. }
  74. lhs.InitializeReferencedBinding(value);
  75. engine._referencePool.Return(lhs);
  76. }
  77. else if (declaration.Init != null)
  78. {
  79. if (declaration.LeftPattern != null)
  80. {
  81. var environment = _statement.Kind != VariableDeclarationKind.Var
  82. ? engine.ExecutionContext.LexicalEnvironment
  83. : null;
  84. var completion = declaration.Init.GetValue(context);
  85. BindingPatternAssignmentExpression.ProcessPatterns(
  86. context,
  87. declaration.LeftPattern,
  88. completion.Value,
  89. environment,
  90. checkPatternPropertyReference: _statement.Kind != VariableDeclarationKind.Var);
  91. }
  92. else if (declaration.LeftIdentifierExpression == null
  93. || JintAssignmentExpression.SimpleAssignmentExpression.AssignToIdentifier(
  94. context,
  95. declaration.LeftIdentifierExpression,
  96. declaration.Init,
  97. declaration.EvalOrArguments) is null)
  98. {
  99. // slow path
  100. var lhs = (Reference) declaration.Left!.Evaluate(context).Value;
  101. lhs.AssertValid(engine.Realm);
  102. var completion = declaration.Init.GetValue(context);
  103. var value = completion.Value.Clone();
  104. if (declaration.Init._expression.IsFunctionDefinition())
  105. {
  106. ((FunctionInstance) value).SetFunctionName(lhs.GetReferencedName());
  107. }
  108. engine.PutValue(lhs, value);
  109. engine._referencePool.Return(lhs);
  110. }
  111. }
  112. }
  113. return VoidCompletion;
  114. }
  115. }
  116. }