Coverage Report

Created: 2025-03-04 07:22

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