JintIdentifierExpression.cs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  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(Engine engine, Identifier expression) : base(engine, 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 object EvaluateInternal()
  22. {
  23. var env = _engine.ExecutionContext.LexicalEnvironment;
  24. var strict = StrictModeScope.IsStrictModeCode;
  25. var identifierEnvironment = JintEnvironment.TryGetIdentifierEnvironmentWithBindingValue(_engine, env, _expressionName, strict, out var temp, out _)
  26. ? temp
  27. : JsValue.Undefined;
  28. return _engine._referencePool.Rent(identifierEnvironment, _expressionName.StringValue, strict, thisValue: null);
  29. }
  30. public override JsValue GetValue()
  31. {
  32. // need to notify correct node when taking shortcut
  33. _engine._lastSyntaxNode = _expression;
  34. if (_calculatedValue is not null)
  35. {
  36. return _calculatedValue;
  37. }
  38. var strict = StrictModeScope.IsStrictModeCode;
  39. var env = _engine.ExecutionContext.LexicalEnvironment;
  40. JsValue value;
  41. if (JintEnvironment.TryGetIdentifierEnvironmentWithBindingValue(
  42. _engine,
  43. env,
  44. _expressionName,
  45. strict,
  46. out _,
  47. out value))
  48. {
  49. if (value is null)
  50. {
  51. ExceptionHelper.ThrowReferenceError(_engine.Realm, _expressionName.Key.Name + " has not been initialized");
  52. }
  53. }
  54. else
  55. {
  56. var reference = _engine._referencePool.Rent(JsValue.Undefined, _expressionName.StringValue, strict, thisValue: null);
  57. value = _engine.GetValue(reference, true);
  58. }
  59. // make sure arguments access freezes state
  60. if (value is ArgumentsInstance argumentsInstance)
  61. {
  62. argumentsInstance.Materialize();
  63. }
  64. return value;
  65. }
  66. }
  67. }