Reference.cs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. using System;
  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;
  7. /// <summary>
  8. /// https://tc39.es/ecma262/#sec-reference-record-specification-type
  9. /// </summary>
  10. public sealed class Reference
  11. {
  12. private JsValue _base;
  13. private JsValue _referencedName;
  14. internal bool _strict;
  15. private JsValue? _thisValue;
  16. internal Reference(JsValue baseValue, JsValue referencedName, bool strict, JsValue? thisValue = null)
  17. {
  18. _base = baseValue;
  19. _referencedName = referencedName;
  20. _thisValue = thisValue;
  21. }
  22. /// <summary>
  23. /// The value or Environment Record which holds the binding. A [[Base]] of unresolvable indicates that the binding could not be resolved.
  24. /// </summary>
  25. public JsValue Base
  26. {
  27. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  28. get => _base;
  29. }
  30. /// <summary>
  31. /// The value or Environment Record which holds the binding. A [[Base]] of unresolvable indicates that the binding could not be resolved.
  32. /// </summary>
  33. public JsValue ReferencedName
  34. {
  35. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  36. get => _referencedName;
  37. }
  38. /// <summary>
  39. /// true if the Reference Record originated in strict mode code, false otherwise.
  40. /// </summary>
  41. public bool Strict
  42. {
  43. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  44. get => _strict;
  45. }
  46. public bool HasPrimitiveBase
  47. {
  48. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  49. get => (_base._type & InternalTypes.Primitive) != InternalTypes.Empty;
  50. }
  51. public bool IsUnresolvableReference
  52. {
  53. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  54. get => _base._type == InternalTypes.Undefined;
  55. }
  56. public bool IsSuperReference => _thisValue is not null;
  57. // https://tc39.es/ecma262/#sec-ispropertyreference
  58. public bool IsPropertyReference
  59. {
  60. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  61. get => (_base._type & (InternalTypes.Primitive | InternalTypes.Object)) != InternalTypes.Empty;
  62. }
  63. public JsValue ThisValue
  64. {
  65. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  66. get => IsSuperReference ? _thisValue! : Base;
  67. }
  68. public bool IsPrivateReference
  69. {
  70. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  71. get => _referencedName._type == InternalTypes.PrivateName;
  72. }
  73. internal Reference Reassign(JsValue baseValue, JsValue name, bool strict, JsValue? thisValue)
  74. {
  75. _base = baseValue;
  76. _referencedName = name;
  77. _strict = strict;
  78. _thisValue = thisValue;
  79. return this;
  80. }
  81. internal void AssertValid(Realm realm)
  82. {
  83. if (_strict
  84. && (_base._type & InternalTypes.ObjectEnvironmentRecord) != InternalTypes.Empty
  85. && (CommonProperties.Eval.Equals(_referencedName) || CommonProperties.Arguments.Equals(_referencedName)))
  86. {
  87. Throw.SyntaxError(realm);
  88. }
  89. }
  90. internal void InitializeReferencedBinding(JsValue value, DisposeHint hint)
  91. {
  92. ((Environment) _base).InitializeBinding(TypeConverter.ToString(_referencedName), value, hint);
  93. }
  94. internal void EvaluateAndCachePropertyKey()
  95. {
  96. if (!(_referencedName.IsInteger() && _base.IsIntegerIndexedArray))
  97. {
  98. _referencedName = Runtime.TypeConverter.ToPropertyKey(_referencedName);
  99. }
  100. }
  101. }
  102. internal enum DisposeHint
  103. {
  104. Normal,
  105. Sync,
  106. Async,
  107. }