JintVariableDeclaration.cs 4.4 KB

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