JintVariableDeclaration.cs 4.9 KB

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