2
0

JintVariableDeclaration.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  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 Completion(CompletionType.Normal, null, null, default);
  11. private ResolvedDeclaration[] _declarations;
  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(Engine engine, VariableDeclaration statement) : base(engine, statement)
  21. {
  22. _initialized = false;
  23. }
  24. protected override void Initialize()
  25. {
  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, 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()
  57. {
  58. if (!_initialized)
  59. {
  60. _initialized = true;
  61. Initialize();
  62. }
  63. foreach (var declaration in _declarations)
  64. {
  65. if (_statement.Kind != VariableDeclarationKind.Var && declaration.Left != null)
  66. {
  67. var lhs = (Reference) declaration.Left.Evaluate();
  68. var value = JsValue.Undefined;
  69. if (declaration.Init != null)
  70. {
  71. value = declaration.Init.GetValue().Clone();
  72. if (declaration.Init._expression.IsFunctionDefinition())
  73. {
  74. ((FunctionInstance) value).SetFunctionName(lhs.GetReferencedName());
  75. }
  76. }
  77. lhs.InitializeReferencedBinding(value);
  78. _engine._referencePool.Return(lhs);
  79. }
  80. else if (declaration.Init != null)
  81. {
  82. if (declaration.LeftPattern != null)
  83. {
  84. var environment = _statement.Kind != VariableDeclarationKind.Var
  85. ? _engine.ExecutionContext.LexicalEnvironment
  86. : null;
  87. BindingPatternAssignmentExpression.ProcessPatterns(
  88. _engine,
  89. declaration.LeftPattern,
  90. declaration.Init.GetValue(),
  91. environment,
  92. checkObjectPatternPropertyReference: _statement.Kind != VariableDeclarationKind.Var);
  93. }
  94. else if (declaration.LeftIdentifierExpression == null
  95. || JintAssignmentExpression.SimpleAssignmentExpression.AssignToIdentifier(
  96. _engine,
  97. declaration.LeftIdentifierExpression,
  98. declaration.Init,
  99. declaration.EvalOrArguments) is null)
  100. {
  101. // slow path
  102. var lhs = (Reference) declaration.Left.Evaluate();
  103. lhs.AssertValid(_engine);
  104. var value = declaration.Init.GetValue().Clone();
  105. if (declaration.Init._expression.IsFunctionDefinition())
  106. {
  107. ((FunctionInstance) value).SetFunctionName(lhs.GetReferencedName());
  108. }
  109. _engine.PutValue(lhs, value);
  110. _engine._referencePool.Return(lhs);
  111. }
  112. }
  113. }
  114. return VoidCompletion;
  115. }
  116. }
  117. }