JintVariableDeclaration.cs 5.0 KB

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