2
0

StringInstance.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. using Jint.Native.Object;
  2. using Jint.Runtime;
  3. using Jint.Runtime.Descriptors;
  4. namespace Jint.Native.String
  5. {
  6. public class StringInstance : ObjectInstance, IPrimitiveInstance
  7. {
  8. internal PropertyDescriptor? _length;
  9. public StringInstance(Engine engine, JsString value)
  10. : base(engine, ObjectClass.String)
  11. {
  12. StringData = value;
  13. _length = PropertyDescriptor.AllForbiddenDescriptor.ForNumber(value.Length);
  14. }
  15. Types IPrimitiveInstance.Type => Types.String;
  16. JsValue IPrimitiveInstance.PrimitiveValue => StringData;
  17. public JsString StringData { get; }
  18. private static bool IsInt32(double d, out int intValue)
  19. {
  20. if (d >= int.MinValue && d <= int.MaxValue)
  21. {
  22. intValue = (int) d;
  23. return intValue == d;
  24. }
  25. intValue = 0;
  26. return false;
  27. }
  28. public override PropertyDescriptor GetOwnProperty(JsValue property)
  29. {
  30. if (property == CommonProperties.Infinity)
  31. {
  32. return PropertyDescriptor.Undefined;
  33. }
  34. if (property == CommonProperties.Length)
  35. {
  36. return _length ?? PropertyDescriptor.Undefined;
  37. }
  38. var desc = base.GetOwnProperty(property);
  39. if (desc != PropertyDescriptor.Undefined)
  40. {
  41. return desc;
  42. }
  43. if ((property._type & (InternalTypes.Number | InternalTypes.Integer | InternalTypes.String)) == 0)
  44. {
  45. return PropertyDescriptor.Undefined;
  46. }
  47. var str = StringData.ToString();
  48. var number = TypeConverter.ToNumber(property);
  49. if (!IsInt32(number, out var index) || index < 0 || index >= str.Length)
  50. {
  51. return PropertyDescriptor.Undefined;
  52. }
  53. return new PropertyDescriptor(str[index], PropertyFlag.OnlyEnumerable);
  54. }
  55. public override IEnumerable<KeyValuePair<JsValue, PropertyDescriptor>> GetOwnProperties()
  56. {
  57. foreach (var entry in base.GetOwnProperties())
  58. {
  59. yield return entry;
  60. }
  61. if (_length != null)
  62. {
  63. yield return new KeyValuePair<JsValue, PropertyDescriptor>(CommonProperties.Length, _length);
  64. }
  65. }
  66. internal override IEnumerable<JsValue> GetInitialOwnStringPropertyKeys()
  67. {
  68. return new[] { JsString.LengthString };
  69. }
  70. public override List<JsValue> GetOwnPropertyKeys(Types types)
  71. {
  72. var keys = new List<JsValue>(StringData.Length + 1);
  73. if ((types & Types.String) != 0)
  74. {
  75. for (uint i = 0; i < StringData.Length; ++i)
  76. {
  77. keys.Add(JsString.Create(i));
  78. }
  79. keys.AddRange(base.GetOwnPropertyKeys(Types.String));
  80. }
  81. if ((types & Types.Symbol) != 0)
  82. {
  83. keys.AddRange(base.GetOwnPropertyKeys(Types.Symbol));
  84. }
  85. return keys;
  86. }
  87. protected internal override void SetOwnProperty(JsValue property, PropertyDescriptor desc)
  88. {
  89. if (property == CommonProperties.Length)
  90. {
  91. _length = desc;
  92. }
  93. else
  94. {
  95. base.SetOwnProperty(property, desc);
  96. }
  97. }
  98. public override void RemoveOwnProperty(JsValue property)
  99. {
  100. if (property == CommonProperties.Length)
  101. {
  102. _length = null;
  103. }
  104. base.RemoveOwnProperty(property);
  105. }
  106. }
  107. }