JintIdentifierExpression.cs 2.6 KB

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