StringInstance.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. using System.Collections.Generic;
  2. using Jint.Native.Object;
  3. using Jint.Runtime;
  4. using Jint.Runtime.Descriptors;
  5. namespace Jint.Native.String
  6. {
  7. public class StringInstance : ObjectInstance, IPrimitiveInstance
  8. {
  9. private const string PropertyNameLength = "length";
  10. private const int PropertyNameLengthLength = 6;
  11. internal PropertyDescriptor _length;
  12. public StringInstance(Engine engine)
  13. : base(engine, objectClass: "String")
  14. {
  15. }
  16. Types IPrimitiveInstance.Type => Types.String;
  17. JsValue IPrimitiveInstance.PrimitiveValue => PrimitiveValue;
  18. public JsString PrimitiveValue { get; set; }
  19. private static bool IsInt(double d)
  20. {
  21. if (d >= long.MinValue && d <= long.MaxValue)
  22. {
  23. var l = (long) d;
  24. return l >= int.MinValue && l <= int.MaxValue;
  25. }
  26. return false;
  27. }
  28. public override PropertyDescriptor GetOwnProperty(string propertyName)
  29. {
  30. if (propertyName.Length == 8 && propertyName == "Infinity")
  31. {
  32. return PropertyDescriptor.Undefined;
  33. }
  34. if (propertyName.Length == PropertyNameLengthLength && propertyName == PropertyNameLength)
  35. {
  36. return _length ?? PropertyDescriptor.Undefined;
  37. }
  38. var desc = base.GetOwnProperty(propertyName);
  39. if (desc != PropertyDescriptor.Undefined)
  40. {
  41. return desc;
  42. }
  43. var integer = TypeConverter.ToInteger(propertyName);
  44. if (integer == 0 && propertyName != "0" || propertyName != System.Math.Abs(integer).ToString())
  45. {
  46. return PropertyDescriptor.Undefined;
  47. }
  48. var str = PrimitiveValue;
  49. var dIndex = integer;
  50. if (!IsInt(dIndex))
  51. return PropertyDescriptor.Undefined;
  52. var index = (int) dIndex;
  53. var len = str.AsStringWithoutTypeCheck().Length;
  54. if (len <= index || index < 0)
  55. {
  56. return PropertyDescriptor.Undefined;
  57. }
  58. var resultStr = TypeConverter.ToString(str.AsStringWithoutTypeCheck()[index]);
  59. return new PropertyDescriptor(resultStr, PropertyFlag.OnlyEnumerable);
  60. }
  61. public override IEnumerable<KeyValuePair<string, PropertyDescriptor>> GetOwnProperties()
  62. {
  63. if (_length != null)
  64. {
  65. yield return new KeyValuePair<string, PropertyDescriptor>(PropertyNameLength, _length);
  66. }
  67. foreach (var entry in base.GetOwnProperties())
  68. {
  69. yield return entry;
  70. }
  71. }
  72. protected internal override void SetOwnProperty(string propertyName, PropertyDescriptor desc)
  73. {
  74. if (propertyName.Length == PropertyNameLengthLength && propertyName == PropertyNameLength)
  75. {
  76. _length = desc;
  77. }
  78. else
  79. {
  80. base.SetOwnProperty(propertyName, desc);
  81. }
  82. }
  83. public override bool HasOwnProperty(string propertyName)
  84. {
  85. if (propertyName.Length == PropertyNameLengthLength && propertyName == PropertyNameLength)
  86. {
  87. return _length != null;
  88. }
  89. return base.HasOwnProperty(propertyName);
  90. }
  91. public override void RemoveOwnProperty(string propertyName)
  92. {
  93. if (propertyName.Length == PropertyNameLengthLength && propertyName == PropertyNameLength)
  94. {
  95. _length = null;
  96. }
  97. base.RemoveOwnProperty(propertyName);
  98. }
  99. }
  100. }