JintMemberExpression.cs 3.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. using Esprima.Ast;
  2. using Jint.Native;
  3. using Jint.Runtime.Environments;
  4. using Jint.Runtime.References;
  5. namespace Jint.Runtime.Interpreter.Expressions
  6. {
  7. /// <summary>
  8. /// http://www.ecma-international.org/ecma-262/5.1/#sec-11.2.1
  9. /// </summary>
  10. internal sealed class JintMemberExpression : JintExpression
  11. {
  12. private JintExpression _objectExpression;
  13. private JintIdentifierExpression _objectIdentifierExpression;
  14. private JintThisExpression _objectThisExpression;
  15. private JintExpression _propertyExpression;
  16. private JsValue _determinedProperty;
  17. public JintMemberExpression(Engine engine, MemberExpression expression) : base(engine, expression)
  18. {
  19. _initialized = false;
  20. }
  21. protected override void Initialize()
  22. {
  23. var expression = (MemberExpression) _expression;
  24. _objectExpression = Build(_engine, expression.Object);
  25. _objectIdentifierExpression = _objectExpression as JintIdentifierExpression;
  26. _objectThisExpression = _objectExpression as JintThisExpression;
  27. if (!expression.Computed)
  28. {
  29. _determinedProperty = ((Identifier) expression.Property).Name;
  30. }
  31. else if (expression.Property.Type == Nodes.Literal)
  32. {
  33. _determinedProperty = JintLiteralExpression.ConvertToJsValue((Literal) expression.Property);
  34. }
  35. if (_determinedProperty is null)
  36. {
  37. _propertyExpression = Build(_engine, expression.Property);
  38. }
  39. }
  40. protected override object EvaluateInternal()
  41. {
  42. string baseReferenceName = null;
  43. JsValue baseValue = null;
  44. var isStrictModeCode = StrictModeScope.IsStrictModeCode;
  45. if (_objectIdentifierExpression != null)
  46. {
  47. baseReferenceName = _objectIdentifierExpression._expressionName.Key.Name;
  48. var strict = isStrictModeCode;
  49. var env = _engine.ExecutionContext.LexicalEnvironment;
  50. LexicalEnvironment.TryGetIdentifierEnvironmentWithBindingValue(
  51. env,
  52. _objectIdentifierExpression._expressionName,
  53. strict,
  54. out _,
  55. out baseValue);
  56. }
  57. else if (_objectThisExpression != null)
  58. {
  59. baseValue = _objectThisExpression.GetValue();
  60. }
  61. if (baseValue is null)
  62. {
  63. // fast checks failed
  64. var baseReference = _objectExpression.Evaluate();
  65. if (baseReference is Reference reference)
  66. {
  67. baseReferenceName = reference.GetReferencedName().ToString();
  68. baseValue = _engine.GetValue(reference, false);
  69. _engine._referencePool.Return(reference);
  70. }
  71. else
  72. {
  73. baseValue = _engine.GetValue(baseReference, false);
  74. }
  75. }
  76. var property = _determinedProperty ?? _propertyExpression.GetValue();
  77. TypeConverter.CheckObjectCoercible(_engine, baseValue, (MemberExpression) _expression, _determinedProperty?.ToString() ?? baseReferenceName);
  78. // only convert if necessary
  79. var propertyKey = property.IsInteger() && baseValue.IsIntegerIndexedArray
  80. ? property
  81. : TypeConverter.ToPropertyKey(property);
  82. return _engine._referencePool.Rent(baseValue, propertyKey, isStrictModeCode);
  83. }
  84. }
  85. }