2
0

JintIdentifierExpression.cs 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  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 strict = StrictModeScope.IsStrictModeCode;
  47. var engine = context.Engine;
  48. var env = engine.ExecutionContext.LexicalEnvironment;
  49. if (JintEnvironment.TryGetIdentifierEnvironmentWithBindingValue(
  50. env,
  51. identifier,
  52. strict,
  53. out _,
  54. out var value))
  55. {
  56. if (value is null)
  57. {
  58. ThrowNotInitialized(engine);
  59. }
  60. }
  61. else
  62. {
  63. var reference = engine._referencePool.Rent(JsValue.Undefined, identifier.Value, strict, thisValue: null);
  64. value = engine.GetValue(reference, returnReferenceToPool: true);
  65. }
  66. // make sure arguments access freezes state
  67. if (value is JsArguments argumentsInstance)
  68. {
  69. argumentsInstance.Materialize();
  70. }
  71. return value;
  72. }
  73. [DoesNotReturn]
  74. [MethodImpl(MethodImplOptions.NoInlining)]
  75. private void ThrowNotInitialized(Engine engine)
  76. {
  77. ExceptionHelper.ThrowReferenceError(engine.Realm, $"{_identifier.Key.Name} has not been initialized");
  78. }
  79. }