JintIdentifierExpression.cs 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  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. {
  9. internal sealed class JintIdentifierExpression : JintExpression
  10. {
  11. public JintIdentifierExpression(Identifier expression) : base(expression)
  12. {
  13. }
  14. internal EnvironmentRecord.BindingName Identifier
  15. {
  16. get => (EnvironmentRecord.BindingName) (_expression.AssociatedData ??= new EnvironmentRecord.BindingName(((Identifier) _expression).Name));
  17. }
  18. public bool HasEvalOrArguments => Identifier.HasEvalOrArguments;
  19. protected override object EvaluateInternal(EvaluationContext context)
  20. {
  21. var engine = context.Engine;
  22. var env = engine.ExecutionContext.LexicalEnvironment;
  23. var strict = StrictModeScope.IsStrictModeCode;
  24. var identifierEnvironment = JintEnvironment.TryGetIdentifierEnvironmentWithBinding(env, Identifier, out var temp)
  25. ? temp
  26. : JsValue.Undefined;
  27. return engine._referencePool.Rent(identifierEnvironment, Identifier.StringValue, 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. if (Identifier.CalculatedValue is not null)
  34. {
  35. return Identifier.CalculatedValue;
  36. }
  37. var strict = StrictModeScope.IsStrictModeCode;
  38. var engine = context.Engine;
  39. var env = engine.ExecutionContext.LexicalEnvironment;
  40. if (JintEnvironment.TryGetIdentifierEnvironmentWithBindingValue(
  41. env,
  42. Identifier,
  43. strict,
  44. out _,
  45. out var value))
  46. {
  47. if (value is null)
  48. {
  49. ThrowNotInitialized(engine);
  50. }
  51. }
  52. else
  53. {
  54. var reference = engine._referencePool.Rent(JsValue.Undefined, Identifier.StringValue, strict, thisValue: null);
  55. value = engine.GetValue(reference, true);
  56. }
  57. // make sure arguments access freezes state
  58. if (value is ArgumentsInstance argumentsInstance)
  59. {
  60. argumentsInstance.Materialize();
  61. }
  62. return value;
  63. }
  64. [DoesNotReturn]
  65. [MethodImpl(MethodImplOptions.NoInlining)]
  66. private void ThrowNotInitialized(Engine engine)
  67. {
  68. ExceptionHelper.ThrowReferenceError(engine.Realm, Identifier.Key.Name + " has not been initialized");
  69. }
  70. }
  71. }