JsRegExp.cs 3.9 KB

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