RegExpLegacyStaticProperties.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /*
  2. * Copyright (c) 2022, LI YUBEI <leeight@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibJS/Runtime/RegExpConstructor.h>
  7. #include <LibJS/Runtime/RegExpLegacyStaticProperties.h>
  8. #include <LibJS/Runtime/VM.h>
  9. namespace JS {
  10. void RegExpLegacyStaticProperties::invalidate()
  11. {
  12. m_input = {};
  13. m_last_match = {};
  14. m_last_paren = {};
  15. m_left_context = {};
  16. m_right_context = {};
  17. m_$1 = {};
  18. m_$2 = {};
  19. m_$3 = {};
  20. m_$4 = {};
  21. m_$5 = {};
  22. m_$6 = {};
  23. m_$7 = {};
  24. m_$8 = {};
  25. m_$9 = {};
  26. }
  27. // GetLegacyRegExpStaticProperty( C, thisValue, internalSlotName ), https://github.com/tc39/proposal-regexp-legacy-features#getlegacyregexpstaticproperty-c-thisvalue-internalslotname-
  28. ThrowCompletionOr<Value> get_legacy_regexp_static_property(VM& vm, RegExpConstructor& constructor, Value this_value, Optional<Utf16String> const& (RegExpLegacyStaticProperties::*property_getter)() const)
  29. {
  30. // 1. Assert C is an object that has an internal slot named internalSlotName.
  31. // 2. If SameValue(C, thisValue) is false, throw a TypeError exception.
  32. if (!same_value(&constructor, this_value))
  33. return vm.throw_completion<TypeError>(ErrorType::GetLegacyRegExpStaticPropertyThisValueMismatch);
  34. // 3. Let val be the value of the internal slot of C named internalSlotName.
  35. auto val = (constructor.legacy_static_properties().*property_getter)();
  36. // 4. If val is empty, throw a TypeError exception.
  37. if (!val.has_value())
  38. return vm.throw_completion<TypeError>(ErrorType::GetLegacyRegExpStaticPropertyValueEmpty);
  39. // 5. Return val.
  40. return js_string(vm, val.release_value());
  41. }
  42. // SetLegacyRegExpStaticProperty( C, thisValue, internalSlotName, val ), https://github.com/tc39/proposal-regexp-legacy-features#setlegacyregexpstaticproperty-c-thisvalue-internalslotname-val-
  43. ThrowCompletionOr<void> set_legacy_regexp_static_property(VM& vm, RegExpConstructor& constructor, Value this_value, void (RegExpLegacyStaticProperties::*property_setter)(Utf16String), Value value)
  44. {
  45. // 1. Assert C is an object that has an internal slot named internalSlotName.
  46. // 2. If SameValue(C, thisValue) is false, throw a TypeError exception.
  47. if (!same_value(&constructor, this_value))
  48. return vm.throw_completion<TypeError>(ErrorType::SetLegacyRegExpStaticPropertyThisValueMismatch);
  49. // 3. Let strVal be ? ToString(val).
  50. auto str_value = TRY(value.to_utf16_string(vm));
  51. // 4. Set the value of the internal slot of C named internalSlotName to strVal.
  52. (constructor.legacy_static_properties().*property_setter)(str_value);
  53. return {};
  54. }
  55. // UpdateLegacyRegExpStaticProperties ( C, S, startIndex, endIndex, capturedValues ), https://github.com/tc39/proposal-regexp-legacy-features#updatelegacyregexpstaticproperties--c-s-startindex-endindex-capturedvalues-
  56. void update_legacy_regexp_static_properties(RegExpConstructor& constructor, Utf16String const& string, size_t start_index, size_t end_index, Vector<Utf16String> const& captured_values)
  57. {
  58. auto& legacy_static_properties = constructor.legacy_static_properties();
  59. // 1. Assert: C is an Object that has a [[RegExpInput]] internal slot.
  60. // 2. Assert: Type(S) is String.
  61. // 3. Let len be the number of code units in S.
  62. auto len = string.length_in_code_units();
  63. // 4. Assert: startIndex and endIndex are integers such that 0 ≤ startIndex ≤ endIndex ≤ len.
  64. VERIFY(start_index <= end_index);
  65. VERIFY(end_index <= len);
  66. // 5. Assert: capturedValues is a List of Strings.
  67. // 6. Let n be the number of elements in capturedValues.
  68. auto group_count = captured_values.size();
  69. // 7. Set the value of C’s [[RegExpInput]] internal slot to S.
  70. legacy_static_properties.set_input(string);
  71. // 8. Set the value of C’s [[RegExpLastMatch]] internal slot to a String whose length is endIndex - startIndex and containing the code units from S with indices startIndex through endIndex - 1, in ascending order.
  72. auto last_match = string.view().substring_view(start_index, end_index - start_index);
  73. legacy_static_properties.set_last_match(Utf16String(last_match));
  74. // 9. If n > 0, set the value of C’s [[RegExpLastParen]] internal slot to the last element of capturedValues.
  75. if (group_count > 0) {
  76. auto item = captured_values[group_count - 1];
  77. legacy_static_properties.set_last_paren(item);
  78. }
  79. // 10. Else, set the value of C’s [[RegExpLastParen]] internal slot to the empty String.
  80. else {
  81. legacy_static_properties.set_last_paren(Utf16String(""sv));
  82. }
  83. // 11. Set the value of C’s [[RegExpLeftContext]] internal slot to a String whose length is startIndex and containing the code units from S with indices 0 through startIndex - 1, in ascending order.
  84. auto left_context = string.view().substring_view(0, start_index);
  85. legacy_static_properties.set_left_context(Utf16String(left_context));
  86. // 12. Set the value of C’s [[RegExpRightContext]] internal slot to a String whose length is len - endIndex and containing the code units from S with indices endIndex through len - 1, in ascending order.
  87. auto right_context = string.view().substring_view(end_index, len - end_index);
  88. legacy_static_properties.set_right_context(Utf16String(right_context));
  89. // 13. For each integer i such that 1 ≤ i ≤ 9
  90. for (size_t i = 1; i <= 9; i++) {
  91. auto value = Utf16String(""sv);
  92. // If i ≤ n, set the value of C’s [[RegExpPareni]] internal slot to the ith element of capturedValues.
  93. if (i <= group_count) {
  94. value = captured_values[i - 1];
  95. }
  96. // Else, set the value of C’s [[RegExpPareni]] internal slot to the empty String.
  97. else {
  98. // It's already an empty string
  99. }
  100. if (i == 1) {
  101. legacy_static_properties.set_$1(Utf16String(value));
  102. } else if (i == 2) {
  103. legacy_static_properties.set_$2(Utf16String(value));
  104. } else if (i == 3) {
  105. legacy_static_properties.set_$3(Utf16String(value));
  106. } else if (i == 4) {
  107. legacy_static_properties.set_$4(Utf16String(value));
  108. } else if (i == 5) {
  109. legacy_static_properties.set_$5(Utf16String(value));
  110. } else if (i == 6) {
  111. legacy_static_properties.set_$6(Utf16String(value));
  112. } else if (i == 7) {
  113. legacy_static_properties.set_$7(Utf16String(value));
  114. } else if (i == 8) {
  115. legacy_static_properties.set_$8(Utf16String(value));
  116. } else if (i == 9) {
  117. legacy_static_properties.set_$9(Utf16String(value));
  118. }
  119. }
  120. }
  121. // InvalidateLegacyRegExpStaticProperties ( C ), https://github.com/tc39/proposal-regexp-legacy-features#invalidatelegacyregexpstaticproperties--c
  122. void invalidate_legacy_regexp_static_properties(RegExpConstructor& constructor)
  123. {
  124. // 1. Assert: C is an Object that has a [[RegExpInput]] internal slot.
  125. // 2. Set the value of the following internal slots of C to empty:
  126. constructor.legacy_static_properties().invalidate();
  127. }
  128. }