JintIdentifierExpression.cs 2.9 KB

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