2
0

JintIdentifierExpression.cs 2.6 KB

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