StringInstance.cs 3.7 KB

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