JintVariableDeclaration.cs 4.9 KB

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