JsRegExp.cs 3.9 KB

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