summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibJS/Runtime/RegExpLegacyStaticProperties.cpp
blob: 50445480379f625a67eddee1158bdbef3ddb4fc9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
 * Copyright (c) 2022, LI YUBEI <leeight@gmail.com>
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#include <AK/Utf16View.h>
#include <LibJS/Runtime/RegExpConstructor.h>
#include <LibJS/Runtime/RegExpLegacyStaticProperties.h>
#include <LibJS/Runtime/VM.h>

namespace JS {

void RegExpLegacyStaticProperties::invalidate()
{
    m_input = {};
    m_last_match = {};
    m_last_paren = {};
    m_left_context = {};
    m_right_context = {};
    m_$1 = {};
    m_$2 = {};
    m_$3 = {};
    m_$4 = {};
    m_$5 = {};
    m_$6 = {};
    m_$7 = {};
    m_$8 = {};
    m_$9 = {};
}

// GetLegacyRegExpStaticProperty( C, thisValue, internalSlotName ), https://github.com/tc39/proposal-regexp-legacy-features#getlegacyregexpstaticproperty-c-thisvalue-internalslotname-
ThrowCompletionOr<Value> get_legacy_regexp_static_property(VM& vm, RegExpConstructor& constructor, Value this_value, Optional<Utf16String> const& (RegExpLegacyStaticProperties::*property_getter)() const)
{
    // 1. Assert C is an object that has an internal slot named internalSlotName.

    // 2. If SameValue(C, thisValue) is false, throw a TypeError exception.
    if (!same_value(&constructor, this_value))
        return vm.throw_completion<TypeError>(ErrorType::GetLegacyRegExpStaticPropertyThisValueMismatch);

    // 3. Let val be the value of the internal slot of C named internalSlotName.
    auto val = (constructor.legacy_static_properties().*property_getter)();

    // 4. If val is empty, throw a TypeError exception.
    if (!val.has_value())
        return vm.throw_completion<TypeError>(ErrorType::GetLegacyRegExpStaticPropertyValueEmpty);

    // 5. Return val.
    return PrimitiveString::create(vm, val.release_value());
}

// SetLegacyRegExpStaticProperty( C, thisValue, internalSlotName, val ), https://github.com/tc39/proposal-regexp-legacy-features#setlegacyregexpstaticproperty-c-thisvalue-internalslotname-val-
ThrowCompletionOr<void> set_legacy_regexp_static_property(VM& vm, RegExpConstructor& constructor, Value this_value, void (RegExpLegacyStaticProperties::*property_setter)(Utf16String), Value value)
{
    // 1. Assert C is an object that has an internal slot named internalSlotName.

    // 2. If SameValue(C, thisValue) is false, throw a TypeError exception.
    if (!same_value(&constructor, this_value))
        return vm.throw_completion<TypeError>(ErrorType::SetLegacyRegExpStaticPropertyThisValueMismatch);

    // 3. Let strVal be ? ToString(val).
    auto str_value = TRY(value.to_utf16_string(vm));

    // 4. Set the value of the internal slot of C named internalSlotName to strVal.
    (constructor.legacy_static_properties().*property_setter)(str_value);

    return {};
}

// UpdateLegacyRegExpStaticProperties ( C, S, startIndex, endIndex, capturedValues ), https://github.com/tc39/proposal-regexp-legacy-features#updatelegacyregexpstaticproperties--c-s-startindex-endindex-capturedvalues-
void update_legacy_regexp_static_properties(RegExpConstructor& constructor, Utf16String const& string, size_t start_index, size_t end_index, Vector<Utf16String> const& captured_values)
{
    auto& legacy_static_properties = constructor.legacy_static_properties();

    // 1. Assert: C is an Object that has a [[RegExpInput]] internal slot.
    // 2. Assert: Type(S) is String.

    // 3. Let len be the number of code units in S.
    auto len = string.length_in_code_units();

    // 4. Assert: startIndex and endIndex are integers such that 0 ≤ startIndex ≤ endIndex ≤ len.
    VERIFY(start_index <= end_index);
    VERIFY(end_index <= len);

    // 5. Assert: capturedValues is a List of Strings.

    // 6. Let n be the number of elements in capturedValues.
    auto group_count = captured_values.size();

    // 7. Set the value of C’s [[RegExpInput]] internal slot to S.
    legacy_static_properties.set_input(string);

    // 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.
    auto last_match = string.view().substring_view(start_index, end_index - start_index);
    legacy_static_properties.set_last_match(Utf16String(last_match));

    // 9. If n > 0, set the value of C’s [[RegExpLastParen]] internal slot to the last element of capturedValues.
    if (group_count > 0) {
        auto item = captured_values[group_count - 1];
        legacy_static_properties.set_last_paren(item);
    }
    // 10. Else, set the value of C’s [[RegExpLastParen]] internal slot to the empty String.
    else {
        legacy_static_properties.set_last_paren(Utf16String(""sv));
    }

    // 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.
    auto left_context = string.view().substring_view(0, start_index);
    legacy_static_properties.set_left_context(Utf16String(left_context));

    // 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.
    auto right_context = string.view().substring_view(end_index, len - end_index);
    legacy_static_properties.set_right_context(Utf16String(right_context));

    // 13. For each integer i such that 1 ≤ i ≤ 9
    for (size_t i = 1; i <= 9; i++) {
        auto value = Utf16String(""sv);
        // If i ≤ n, set the value of C’s [[RegExpPareni]] internal slot to the ith element of capturedValues.
        if (i <= group_count) {
            value = captured_values[i - 1];
        }
        // Else, set the value of C’s [[RegExpPareni]] internal slot to the empty String.
        else {
            // It's already an empty string
        }

        if (i == 1) {
            legacy_static_properties.set_$1(Utf16String(value));
        } else if (i == 2) {
            legacy_static_properties.set_$2(Utf16String(value));
        } else if (i == 3) {
            legacy_static_properties.set_$3(Utf16String(value));
        } else if (i == 4) {
            legacy_static_properties.set_$4(Utf16String(value));
        } else if (i == 5) {
            legacy_static_properties.set_$5(Utf16String(value));
        } else if (i == 6) {
            legacy_static_properties.set_$6(Utf16String(value));
        } else if (i == 7) {
            legacy_static_properties.set_$7(Utf16String(value));
        } else if (i == 8) {
            legacy_static_properties.set_$8(Utf16String(value));
        } else if (i == 9) {
            legacy_static_properties.set_$9(Utf16String(value));
        }
    }
}

// InvalidateLegacyRegExpStaticProperties ( C ), https://github.com/tc39/proposal-regexp-legacy-features#invalidatelegacyregexpstaticproperties--c
void invalidate_legacy_regexp_static_properties(RegExpConstructor& constructor)
{
    // 1. Assert: C is an Object that has a [[RegExpInput]] internal slot.

    // 2. Set the value of the following internal slots of C to empty:
    constructor.legacy_static_properties().invalidate();
}

}