JsRegExp.cs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. using System.Text.RegularExpressions;
  2. using Jint.Native.Object;
  3. using Jint.Native.RegExp;
  4. using Jint.Runtime;
  5. using Jint.Runtime.Descriptors;
  6. namespace Jint.Native;
  7. public sealed class JsRegExp : ObjectInstance
  8. {
  9. internal const string regExpForMatchingAllCharacters = "(?:)";
  10. internal static readonly JsString PropertyLastIndex = new("lastIndex");
  11. private string _flags = null!;
  12. private PropertyDescriptor _prototypeDescriptor = null!;
  13. public JsRegExp(Engine engine)
  14. : base(engine, ObjectClass.RegExp)
  15. {
  16. Source = regExpForMatchingAllCharacters;
  17. }
  18. public Regex Value { get; set; } = null!;
  19. public string Source { get; set; }
  20. public string Flags
  21. {
  22. get => _flags;
  23. set
  24. {
  25. _flags = value;
  26. foreach (var c in _flags)
  27. {
  28. switch (c)
  29. {
  30. case 'd':
  31. Indices = true;
  32. break;
  33. case 'i':
  34. IgnoreCase = true;
  35. break;
  36. case 'm':
  37. Multiline = true;
  38. break;
  39. case 'g':
  40. Global = true;
  41. break;
  42. case 's':
  43. DotAll = true;
  44. break;
  45. case 'y':
  46. Sticky = true;
  47. break;
  48. case 'u':
  49. FullUnicode = true;
  50. break;
  51. case 'v':
  52. UnicodeSets = true;
  53. break;
  54. }
  55. }
  56. }
  57. }
  58. public RegExpParseResult ParseResult { get; set; }
  59. public bool DotAll { get; private set; }
  60. public bool Global { get; private set; }
  61. public bool Indices { get; private set; }
  62. public bool IgnoreCase { get; private set; }
  63. public bool Multiline { get; private set; }
  64. public bool Sticky { get; private set; }
  65. public bool FullUnicode { get; private set; }
  66. public bool UnicodeSets { get; private set; }
  67. internal bool HasDefaultRegExpExec => Properties == null && Prototype is RegExpPrototype { HasDefaultExec: true };
  68. public override PropertyDescriptor GetOwnProperty(JsValue property)
  69. {
  70. if (PropertyLastIndex.Equals(property))
  71. {
  72. return _prototypeDescriptor ?? PropertyDescriptor.Undefined;
  73. }
  74. return base.GetOwnProperty(property);
  75. }
  76. protected internal override void SetOwnProperty(JsValue property, PropertyDescriptor desc)
  77. {
  78. if (PropertyLastIndex.Equals(property))
  79. {
  80. _prototypeDescriptor = desc;
  81. return;
  82. }
  83. base.SetOwnProperty(property, desc);
  84. }
  85. public override IEnumerable<KeyValuePair<JsValue, PropertyDescriptor>> GetOwnProperties()
  86. {
  87. if (_prototypeDescriptor != null)
  88. {
  89. yield return new KeyValuePair<JsValue, PropertyDescriptor>(PropertyLastIndex, _prototypeDescriptor);
  90. }
  91. foreach (var entry in base.GetOwnProperties())
  92. {
  93. yield return entry;
  94. }
  95. }
  96. public override List<JsValue> GetOwnPropertyKeys(Types types = Types.String | Types.Symbol)
  97. {
  98. var keys = new List<JsValue>();
  99. if (_prototypeDescriptor != null)
  100. {
  101. keys.Add(PropertyLastIndex);
  102. }
  103. keys.AddRange(base.GetOwnPropertyKeys(types));
  104. return keys;
  105. }
  106. }