JintIdentifierExpression.cs 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. using Esprima.Ast;
  2. using Jint.Native;
  3. using Jint.Native.Argument;
  4. using Jint.Runtime.Environments;
  5. namespace Jint.Runtime.Interpreter.Expressions
  6. {
  7. internal sealed class JintIdentifierExpression : JintExpression
  8. {
  9. internal readonly EnvironmentRecord.BindingName _expressionName;
  10. private readonly JsValue _calculatedValue;
  11. public JintIdentifierExpression(Identifier expression) : base(expression)
  12. {
  13. _expressionName = new EnvironmentRecord.BindingName(expression.Name);
  14. if (expression.Name == "undefined")
  15. {
  16. _calculatedValue = JsValue.Undefined;
  17. }
  18. }
  19. public bool HasEvalOrArguments
  20. => _expressionName.Key == KnownKeys.Eval || _expressionName.Key == KnownKeys.Arguments;
  21. protected override ExpressionResult EvaluateInternal(EvaluationContext context)
  22. {
  23. var engine = context.Engine;
  24. var env = engine.ExecutionContext.LexicalEnvironment;
  25. var strict = StrictModeScope.IsStrictModeCode;
  26. var identifierEnvironment = JintEnvironment.TryGetIdentifierEnvironmentWithBindingValue(engine, env, _expressionName, strict, out var temp, out _)
  27. ? temp
  28. : JsValue.Undefined;
  29. return NormalCompletion(engine._referencePool.Rent(identifierEnvironment, _expressionName.StringValue, strict, thisValue: null));
  30. }
  31. public override Completion GetValue(EvaluationContext context)
  32. {
  33. // need to notify correct node when taking shortcut
  34. context.LastSyntaxNode = _expression;
  35. if (_calculatedValue is not null)
  36. {
  37. return Completion.Normal(_calculatedValue, _expression.Location);
  38. }
  39. var strict = StrictModeScope.IsStrictModeCode;
  40. var engine = context.Engine;
  41. var env = engine.ExecutionContext.LexicalEnvironment;
  42. if (JintEnvironment.TryGetIdentifierEnvironmentWithBindingValue(
  43. engine,
  44. env,
  45. _expressionName,
  46. strict,
  47. out _,
  48. out var value))
  49. {
  50. if (value is null)
  51. {
  52. ExceptionHelper.ThrowReferenceError(engine.Realm, _expressionName.Key.Name + " has not been initialized");
  53. }
  54. }
  55. else
  56. {
  57. var reference = engine._referencePool.Rent(JsValue.Undefined, _expressionName.StringValue, strict, thisValue: null);
  58. value = engine.GetValue(reference, true);
  59. }
  60. // make sure arguments access freezes state
  61. if (value is ArgumentsInstance argumentsInstance)
  62. {
  63. argumentsInstance.Materialize();
  64. }
  65. return Completion.Normal(value, _expression.Location);
  66. }
  67. }
  68. }