2022-10-17 08:59:27 +08:00
/*
* Copyright ( c ) 2022 , LI YUBEI < leeight @ gmail . com >
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
2022-11-23 12:45:58 +01:00
# include <AK/Utf16View.h>
2022-10-17 08:59:27 +08:00
# include <LibJS/Runtime/RegExpConstructor.h>
# include <LibJS/Runtime/RegExpLegacyStaticProperties.h>
# include <LibJS/Runtime/VM.h>
namespace JS {
void RegExpLegacyStaticProperties : : invalidate ( )
{
2026-04-10 18:37:08 +02:00
m_input = nullptr ;
m_match_source = nullptr ;
m_last_match_start = 0 ;
m_last_match_length = 0 ;
m_last_match_string = nullptr ;
m_last_paren = nullptr ;
m_last_paren_start = - 1 ;
m_last_paren_end = - 1 ;
m_left_context_start = 0 ;
m_left_context_length = 0 ;
m_left_context_string = nullptr ;
m_right_context_start = 0 ;
m_right_context_length = 0 ;
m_right_context_string = nullptr ;
LibJS+LibRegex: Switch RegExp over to the Rust engine
Switch LibJS `RegExp` over to the Rust-backed `ECMAScriptRegex` APIs.
Route `new RegExp()`, regex literals, and the RegExp builtins through
the new compile and exec APIs, and stop re-validating patterns with the
deleted C++ parser on the way in. Preserve the observable error
behavior by carrying structured compile errors and backtracking-limit
failures across the FFI boundary. Cache compiled regex state and named
capture metadata on `RegExpObject` in the new representation.
Use the new API surface to simplify and speed up the builtin paths too:
share `exec_internal`, cache compiled regex pointers, keep the legacy
RegExp statics lazy, run global replace through batch `find_all`, and
optimize replace, test, split, and String helper paths. Add regression
tests for those JavaScript-visible paths.
2026-03-25 10:52:40 +01:00
for ( auto & p : m_ $ )
2026-04-10 18:37:08 +02:00
p = nullptr ;
LibJS+LibRegex: Switch RegExp over to the Rust engine
Switch LibJS `RegExp` over to the Rust-backed `ECMAScriptRegex` APIs.
Route `new RegExp()`, regex literals, and the RegExp builtins through
the new compile and exec APIs, and stop re-validating patterns with the
deleted C++ parser on the way in. Preserve the observable error
behavior by carrying structured compile errors and backtracking-limit
failures across the FFI boundary. Cache compiled regex state and named
capture metadata on `RegExpObject` in the new representation.
Use the new API surface to simplify and speed up the builtin paths too:
share `exec_internal`, cache compiled regex pointers, keep the legacy
RegExp statics lazy, run global replace through batch `find_all`, and
optimize replace, test, split, and String helper paths. Add regression
tests for those JavaScript-visible paths.
2026-03-25 10:52:40 +01:00
for ( auto & s : m_paren_starts )
s = - 1 ;
for ( auto & e : m_paren_ends )
e = - 1 ;
m_parens_materialized = true ;
}
2026-04-10 18:37:08 +02:00
void RegExpLegacyStaticProperties : : visit_edges ( Cell : : Visitor & visitor )
{
visitor . visit ( m_input ) ;
visitor . visit ( m_match_source ) ;
visitor . visit ( m_last_paren ) ;
for ( auto & paren : m_ $ )
visitor . visit ( paren ) ;
visitor . visit ( m_last_match_string ) ;
visitor . visit ( m_left_context_string ) ;
visitor . visit ( m_right_context_string ) ;
}
void RegExpLegacyStaticProperties : : set_match_source ( GC : : Ref < PrimitiveString > match_source )
{
m_match_source = match_source ;
m_last_match_string = nullptr ;
m_last_paren = nullptr ;
m_left_context_string = nullptr ;
m_right_context_string = nullptr ;
for ( auto & paren : m_ $ )
paren = nullptr ;
}
void RegExpLegacyStaticProperties : : set_last_match ( size_t start , size_t length )
{
m_last_match_start = start ;
m_last_match_length = length ;
m_last_match_string = nullptr ;
}
void RegExpLegacyStaticProperties : : set_last_paren ( GC : : Ref < PrimitiveString > last_paren )
{
m_last_paren = last_paren ;
m_last_paren_start = - 1 ;
m_last_paren_end = - 1 ;
}
void RegExpLegacyStaticProperties : : set_left_context ( size_t start , size_t length )
{
m_left_context_start = start ;
m_left_context_length = length ;
m_left_context_string = nullptr ;
}
void RegExpLegacyStaticProperties : : set_right_context ( size_t start , size_t length )
{
m_right_context_start = start ;
m_right_context_length = length ;
m_right_context_string = nullptr ;
}
GC : : Ref < PrimitiveString > RegExpLegacyStaticProperties : : empty_string ( ) const
{
VERIFY ( m_match_source ) ;
return m_match_source - > vm ( ) . empty_string ( ) ;
}
GC : : Ref < PrimitiveString > RegExpLegacyStaticProperties : : substring_of_match_source ( size_t start , size_t length ) const
{
VERIFY ( m_match_source ) ;
return PrimitiveString : : create ( m_match_source - > vm ( ) , * m_match_source , start , length ) ;
}
GC : : Ptr < PrimitiveString > RegExpLegacyStaticProperties : : last_match ( ) const
{
if ( ! m_match_source )
return nullptr ;
if ( ! m_last_match_string )
m_last_match_string = substring_of_match_source ( m_last_match_start , m_last_match_length ) ;
return m_last_match_string ;
}
GC : : Ptr < PrimitiveString > RegExpLegacyStaticProperties : : last_paren ( ) const
{
if ( ! m_match_source )
return nullptr ;
if ( ! m_last_paren ) {
if ( m_last_paren_start > = 0 & & m_last_paren_end > = 0 )
m_last_paren = substring_of_match_source ( m_last_paren_start , m_last_paren_end - m_last_paren_start ) ;
else
m_last_paren = empty_string ( ) ;
}
return m_last_paren ;
}
GC : : Ptr < PrimitiveString > RegExpLegacyStaticProperties : : left_context ( ) const
{
if ( ! m_match_source )
return nullptr ;
if ( ! m_left_context_string )
m_left_context_string = substring_of_match_source ( m_left_context_start , m_left_context_length ) ;
return m_left_context_string ;
}
GC : : Ptr < PrimitiveString > RegExpLegacyStaticProperties : : right_context ( ) const
{
if ( ! m_match_source )
return nullptr ;
if ( ! m_right_context_string )
m_right_context_string = substring_of_match_source ( m_right_context_start , m_right_context_length ) ;
return m_right_context_string ;
}
GC : : Ptr < PrimitiveString > RegExpLegacyStaticProperties : : lazy_paren ( size_t index ) const
LibJS+LibRegex: Switch RegExp over to the Rust engine
Switch LibJS `RegExp` over to the Rust-backed `ECMAScriptRegex` APIs.
Route `new RegExp()`, regex literals, and the RegExp builtins through
the new compile and exec APIs, and stop re-validating patterns with the
deleted C++ parser on the way in. Preserve the observable error
behavior by carrying structured compile errors and backtracking-limit
failures across the FFI boundary. Cache compiled regex state and named
capture metadata on `RegExpObject` in the new representation.
Use the new API surface to simplify and speed up the builtin paths too:
share `exec_internal`, cache compiled regex pointers, keep the legacy
RegExp statics lazy, run global replace through batch `find_all`, and
optimize replace, test, split, and String helper paths. Add regression
tests for those JavaScript-visible paths.
2026-03-25 10:52:40 +01:00
{
VERIFY ( index < 9 ) ;
2026-04-10 18:37:08 +02:00
if ( ! m_match_source )
return nullptr ;
LibJS+LibRegex: Switch RegExp over to the Rust engine
Switch LibJS `RegExp` over to the Rust-backed `ECMAScriptRegex` APIs.
Route `new RegExp()`, regex literals, and the RegExp builtins through
the new compile and exec APIs, and stop re-validating patterns with the
deleted C++ parser on the way in. Preserve the observable error
behavior by carrying structured compile errors and backtracking-limit
failures across the FFI boundary. Cache compiled regex state and named
capture metadata on `RegExpObject` in the new representation.
Use the new API surface to simplify and speed up the builtin paths too:
share `exec_internal`, cache compiled regex pointers, keep the legacy
RegExp statics lazy, run global replace through batch `find_all`, and
optimize replace, test, split, and String helper paths. Add regression
tests for those JavaScript-visible paths.
2026-03-25 10:52:40 +01:00
if ( ! m_parens_materialized ) {
// Materialize all lazy parens from stored indices.
for ( size_t i = 0 ; i < 9 ; i + + ) {
2026-04-10 18:37:08 +02:00
if ( m_paren_starts [ i ] > = 0 & & m_paren_ends [ i ] > = 0 )
m_ $ [ i ] = substring_of_match_source ( m_paren_starts [ i ] , m_paren_ends [ i ] - m_paren_starts [ i ] ) ;
else
m_ $ [ i ] = empty_string ( ) ;
LibJS+LibRegex: Switch RegExp over to the Rust engine
Switch LibJS `RegExp` over to the Rust-backed `ECMAScriptRegex` APIs.
Route `new RegExp()`, regex literals, and the RegExp builtins through
the new compile and exec APIs, and stop re-validating patterns with the
deleted C++ parser on the way in. Preserve the observable error
behavior by carrying structured compile errors and backtracking-limit
failures across the FFI boundary. Cache compiled regex state and named
capture metadata on `RegExpObject` in the new representation.
Use the new API surface to simplify and speed up the builtin paths too:
share `exec_internal`, cache compiled regex pointers, keep the legacy
RegExp statics lazy, run global replace through batch `find_all`, and
optimize replace, test, split, and String helper paths. Add regression
tests for those JavaScript-visible paths.
2026-03-25 10:52:40 +01:00
}
m_parens_materialized = true ;
}
return m_ $ [ index ] ;
}
void RegExpLegacyStaticProperties : : set_captures_lazy ( size_t num_captures , int const * capture_starts , int const * capture_ends )
{
for ( size_t i = 0 ; i < 9 ; i + + ) {
if ( i < num_captures ) {
m_paren_starts [ i ] = capture_starts [ i ] ;
m_paren_ends [ i ] = capture_ends [ i ] ;
} else {
m_paren_starts [ i ] = - 1 ;
m_paren_ends [ i ] = - 1 ;
}
}
// Clear any previously materialized strings.
for ( auto & p : m_ $ )
2026-04-10 18:37:08 +02:00
p = nullptr ;
LibJS+LibRegex: Switch RegExp over to the Rust engine
Switch LibJS `RegExp` over to the Rust-backed `ECMAScriptRegex` APIs.
Route `new RegExp()`, regex literals, and the RegExp builtins through
the new compile and exec APIs, and stop re-validating patterns with the
deleted C++ parser on the way in. Preserve the observable error
behavior by carrying structured compile errors and backtracking-limit
failures across the FFI boundary. Cache compiled regex state and named
capture metadata on `RegExpObject` in the new representation.
Use the new API surface to simplify and speed up the builtin paths too:
share `exec_internal`, cache compiled regex pointers, keep the legacy
RegExp statics lazy, run global replace through batch `find_all`, and
optimize replace, test, split, and String helper paths. Add regression
tests for those JavaScript-visible paths.
2026-03-25 10:52:40 +01:00
m_parens_materialized = false ;
// Set last_paren to the last captured value.
2026-04-10 18:37:08 +02:00
if ( num_captures > 0 & & capture_starts [ num_captures - 1 ] > = 0 & & capture_ends [ num_captures - 1 ] > = 0 ) {
m_last_paren = nullptr ;
m_last_paren_start = capture_starts [ num_captures - 1 ] ;
m_last_paren_end = capture_ends [ num_captures - 1 ] ;
LibJS+LibRegex: Switch RegExp over to the Rust engine
Switch LibJS `RegExp` over to the Rust-backed `ECMAScriptRegex` APIs.
Route `new RegExp()`, regex literals, and the RegExp builtins through
the new compile and exec APIs, and stop re-validating patterns with the
deleted C++ parser on the way in. Preserve the observable error
behavior by carrying structured compile errors and backtracking-limit
failures across the FFI boundary. Cache compiled regex state and named
capture metadata on `RegExpObject` in the new representation.
Use the new API surface to simplify and speed up the builtin paths too:
share `exec_internal`, cache compiled regex pointers, keep the legacy
RegExp statics lazy, run global replace through batch `find_all`, and
optimize replace, test, split, and String helper paths. Add regression
tests for those JavaScript-visible paths.
2026-03-25 10:52:40 +01:00
} else {
2026-04-10 18:37:08 +02:00
m_last_paren = empty_string ( ) ;
m_last_paren_start = - 1 ;
m_last_paren_end = - 1 ;
LibJS+LibRegex: Switch RegExp over to the Rust engine
Switch LibJS `RegExp` over to the Rust-backed `ECMAScriptRegex` APIs.
Route `new RegExp()`, regex literals, and the RegExp builtins through
the new compile and exec APIs, and stop re-validating patterns with the
deleted C++ parser on the way in. Preserve the observable error
behavior by carrying structured compile errors and backtracking-limit
failures across the FFI boundary. Cache compiled regex state and named
capture metadata on `RegExpObject` in the new representation.
Use the new API surface to simplify and speed up the builtin paths too:
share `exec_internal`, cache compiled regex pointers, keep the legacy
RegExp statics lazy, run global replace through batch `find_all`, and
optimize replace, test, split, and String helper paths. Add regression
tests for those JavaScript-visible paths.
2026-03-25 10:52:40 +01:00
}
2022-10-17 08:59:27 +08:00
}
// GetLegacyRegExpStaticProperty( C, thisValue, internalSlotName ), https://github.com/tc39/proposal-regexp-legacy-features#getlegacyregexpstaticproperty-c-thisvalue-internalslotname-
2026-04-10 18:37:08 +02:00
ThrowCompletionOr < Value > get_legacy_regexp_static_property ( VM & vm , RegExpConstructor & constructor , Value this_value , GC : : Ptr < PrimitiveString > ( RegExpLegacyStaticProperties : : * property_getter ) ( ) const )
2022-10-17 08:59:27 +08:00
{
// 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.
2026-04-10 18:37:08 +02:00
if ( ! val )
2022-10-17 08:59:27 +08:00
return vm . throw_completion < TypeError > ( ErrorType : : GetLegacyRegExpStaticPropertyValueEmpty ) ;
// 5. Return val.
2026-04-10 18:37:08 +02:00
return val ;
2022-10-17 08:59:27 +08:00
}
// SetLegacyRegExpStaticProperty( C, thisValue, internalSlotName, val ), https://github.com/tc39/proposal-regexp-legacy-features#setlegacyregexpstaticproperty-c-thisvalue-internalslotname-val-
2026-04-10 18:37:08 +02:00
ThrowCompletionOr < void > set_legacy_regexp_static_property ( VM & vm , RegExpConstructor & constructor , Value this_value , void ( RegExpLegacyStaticProperties : : * property_setter ) ( GC : : Ref < PrimitiveString > ) , Value value )
2022-10-17 08:59:27 +08:00
{
// 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).
2026-04-10 18:37:08 +02:00
auto str_value = TRY ( value . to_primitive_string ( vm ) ) ;
2022-10-17 08:59:27 +08:00
// 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-
2026-04-10 18:37:08 +02:00
void update_legacy_regexp_static_properties ( RegExpConstructor & constructor , GC : : Ref < PrimitiveString > string , size_t start_index , size_t end_index , Vector < GC : : Ref < PrimitiveString > > const & captured_values )
2022-10-17 08:59:27 +08:00
{
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.
2026-04-10 18:37:08 +02:00
auto len = string - > length_in_utf16_code_units ( ) ;
2022-10-17 08:59:27 +08:00
// 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.
2022-10-19 15:35:35 +02:00
legacy_static_properties . set_input ( string ) ;
2026-04-10 18:37:08 +02:00
legacy_static_properties . set_match_source ( string ) ;
2022-10-17 08:59:27 +08:00
// 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.
2026-04-10 18:37:08 +02:00
legacy_static_properties . set_last_match ( start_index , end_index - start_index ) ;
2022-10-17 08:59:27 +08:00
// 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 {
2026-04-10 18:37:08 +02:00
legacy_static_properties . set_last_paren ( string - > vm ( ) . empty_string ( ) ) ;
2022-10-17 08:59:27 +08:00
}
// 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.
2026-04-10 18:37:08 +02:00
legacy_static_properties . set_left_context ( 0 , start_index ) ;
2022-10-17 08:59:27 +08:00
// 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.
2026-04-10 18:37:08 +02:00
legacy_static_properties . set_right_context ( end_index , len - end_index ) ;
2022-10-17 08:59:27 +08:00
// 13. For each integer i such that 1 ≤ i ≤ 9
for ( size_t i = 1 ; i < = 9 ; i + + ) {
2023-01-07 12:24:05 -05:00
// i. If i ≤ n, set the value of C’ s [[RegExpPareni]] internal slot to the ith element of capturedValues.
// ii. Else, set the value of C’ s [[RegExpPareni]] internal slot to the empty String.
2026-04-10 18:37:08 +02:00
GC : : Ref < PrimitiveString > value = string - > vm ( ) . empty_string ( ) ;
if ( i < = group_count )
value = captured_values [ i - 1 ] ;
2022-10-17 08:59:27 +08:00
if ( i = = 1 ) {
2023-01-07 12:24:05 -05:00
legacy_static_properties . set_ $ 1 ( move ( value ) ) ;
2022-10-17 08:59:27 +08:00
} else if ( i = = 2 ) {
2023-01-07 12:24:05 -05:00
legacy_static_properties . set_ $ 2 ( move ( value ) ) ;
2022-10-17 08:59:27 +08:00
} else if ( i = = 3 ) {
2023-01-07 12:24:05 -05:00
legacy_static_properties . set_ $ 3 ( move ( value ) ) ;
2022-10-17 08:59:27 +08:00
} else if ( i = = 4 ) {
2023-01-07 12:24:05 -05:00
legacy_static_properties . set_ $ 4 ( move ( value ) ) ;
2022-10-17 08:59:27 +08:00
} else if ( i = = 5 ) {
2023-01-07 12:24:05 -05:00
legacy_static_properties . set_ $ 5 ( move ( value ) ) ;
2022-10-17 08:59:27 +08:00
} else if ( i = = 6 ) {
2023-01-07 12:24:05 -05:00
legacy_static_properties . set_ $ 6 ( move ( value ) ) ;
2022-10-17 08:59:27 +08:00
} else if ( i = = 7 ) {
2023-01-07 12:24:05 -05:00
legacy_static_properties . set_ $ 7 ( move ( value ) ) ;
2022-10-17 08:59:27 +08:00
} else if ( i = = 8 ) {
2023-01-07 12:24:05 -05:00
legacy_static_properties . set_ $ 8 ( move ( value ) ) ;
2022-10-17 08:59:27 +08:00
} else if ( i = = 9 ) {
2023-01-07 12:24:05 -05:00
legacy_static_properties . set_ $ 9 ( move ( value ) ) ;
2022-10-17 08:59:27 +08:00
}
}
}
LibJS+LibRegex: Switch RegExp over to the Rust engine
Switch LibJS `RegExp` over to the Rust-backed `ECMAScriptRegex` APIs.
Route `new RegExp()`, regex literals, and the RegExp builtins through
the new compile and exec APIs, and stop re-validating patterns with the
deleted C++ parser on the way in. Preserve the observable error
behavior by carrying structured compile errors and backtracking-limit
failures across the FFI boundary. Cache compiled regex state and named
capture metadata on `RegExpObject` in the new representation.
Use the new API surface to simplify and speed up the builtin paths too:
share `exec_internal`, cache compiled regex pointers, keep the legacy
RegExp statics lazy, run global replace through batch `find_all`, and
optimize replace, test, split, and String helper paths. Add regression
tests for those JavaScript-visible paths.
2026-03-25 10:52:40 +01:00
// Like update_legacy_regexp_static_properties, but defers $1-$9 string creation.
// Captures are stored as index pairs into the input string and materialized on access.
2026-04-10 18:37:08 +02:00
void update_legacy_regexp_static_properties_lazy ( RegExpConstructor & constructor , GC : : Ref < PrimitiveString > string , size_t start_index , size_t end_index , size_t num_captures , int const * capture_starts , int const * capture_ends )
LibJS+LibRegex: Switch RegExp over to the Rust engine
Switch LibJS `RegExp` over to the Rust-backed `ECMAScriptRegex` APIs.
Route `new RegExp()`, regex literals, and the RegExp builtins through
the new compile and exec APIs, and stop re-validating patterns with the
deleted C++ parser on the way in. Preserve the observable error
behavior by carrying structured compile errors and backtracking-limit
failures across the FFI boundary. Cache compiled regex state and named
capture metadata on `RegExpObject` in the new representation.
Use the new API surface to simplify and speed up the builtin paths too:
share `exec_internal`, cache compiled regex pointers, keep the legacy
RegExp statics lazy, run global replace through batch `find_all`, and
optimize replace, test, split, and String helper paths. Add regression
tests for those JavaScript-visible paths.
2026-03-25 10:52:40 +01:00
{
auto & legacy_static_properties = constructor . legacy_static_properties ( ) ;
2026-04-10 18:37:08 +02:00
auto len = string - > length_in_utf16_code_units ( ) ;
LibJS+LibRegex: Switch RegExp over to the Rust engine
Switch LibJS `RegExp` over to the Rust-backed `ECMAScriptRegex` APIs.
Route `new RegExp()`, regex literals, and the RegExp builtins through
the new compile and exec APIs, and stop re-validating patterns with the
deleted C++ parser on the way in. Preserve the observable error
behavior by carrying structured compile errors and backtracking-limit
failures across the FFI boundary. Cache compiled regex state and named
capture metadata on `RegExpObject` in the new representation.
Use the new API surface to simplify and speed up the builtin paths too:
share `exec_internal`, cache compiled regex pointers, keep the legacy
RegExp statics lazy, run global replace through batch `find_all`, and
optimize replace, test, split, and String helper paths. Add regression
tests for those JavaScript-visible paths.
2026-03-25 10:52:40 +01:00
VERIFY ( start_index < = end_index ) ;
VERIFY ( end_index < = len ) ;
legacy_static_properties . set_input ( string ) ;
2026-04-10 18:37:08 +02:00
legacy_static_properties . set_match_source ( string ) ;
LibJS+LibRegex: Switch RegExp over to the Rust engine
Switch LibJS `RegExp` over to the Rust-backed `ECMAScriptRegex` APIs.
Route `new RegExp()`, regex literals, and the RegExp builtins through
the new compile and exec APIs, and stop re-validating patterns with the
deleted C++ parser on the way in. Preserve the observable error
behavior by carrying structured compile errors and backtracking-limit
failures across the FFI boundary. Cache compiled regex state and named
capture metadata on `RegExpObject` in the new representation.
Use the new API surface to simplify and speed up the builtin paths too:
share `exec_internal`, cache compiled regex pointers, keep the legacy
RegExp statics lazy, run global replace through batch `find_all`, and
optimize replace, test, split, and String helper paths. Add regression
tests for those JavaScript-visible paths.
2026-03-25 10:52:40 +01:00
2026-04-10 18:37:08 +02:00
legacy_static_properties . set_last_match ( start_index , end_index - start_index ) ;
LibJS+LibRegex: Switch RegExp over to the Rust engine
Switch LibJS `RegExp` over to the Rust-backed `ECMAScriptRegex` APIs.
Route `new RegExp()`, regex literals, and the RegExp builtins through
the new compile and exec APIs, and stop re-validating patterns with the
deleted C++ parser on the way in. Preserve the observable error
behavior by carrying structured compile errors and backtracking-limit
failures across the FFI boundary. Cache compiled regex state and named
capture metadata on `RegExpObject` in the new representation.
Use the new API surface to simplify and speed up the builtin paths too:
share `exec_internal`, cache compiled regex pointers, keep the legacy
RegExp statics lazy, run global replace through batch `find_all`, and
optimize replace, test, split, and String helper paths. Add regression
tests for those JavaScript-visible paths.
2026-03-25 10:52:40 +01:00
2026-04-10 18:37:08 +02:00
legacy_static_properties . set_left_context ( 0 , start_index ) ;
LibJS+LibRegex: Switch RegExp over to the Rust engine
Switch LibJS `RegExp` over to the Rust-backed `ECMAScriptRegex` APIs.
Route `new RegExp()`, regex literals, and the RegExp builtins through
the new compile and exec APIs, and stop re-validating patterns with the
deleted C++ parser on the way in. Preserve the observable error
behavior by carrying structured compile errors and backtracking-limit
failures across the FFI boundary. Cache compiled regex state and named
capture metadata on `RegExpObject` in the new representation.
Use the new API surface to simplify and speed up the builtin paths too:
share `exec_internal`, cache compiled regex pointers, keep the legacy
RegExp statics lazy, run global replace through batch `find_all`, and
optimize replace, test, split, and String helper paths. Add regression
tests for those JavaScript-visible paths.
2026-03-25 10:52:40 +01:00
2026-04-10 18:37:08 +02:00
legacy_static_properties . set_right_context ( end_index , len - end_index ) ;
LibJS+LibRegex: Switch RegExp over to the Rust engine
Switch LibJS `RegExp` over to the Rust-backed `ECMAScriptRegex` APIs.
Route `new RegExp()`, regex literals, and the RegExp builtins through
the new compile and exec APIs, and stop re-validating patterns with the
deleted C++ parser on the way in. Preserve the observable error
behavior by carrying structured compile errors and backtracking-limit
failures across the FFI boundary. Cache compiled regex state and named
capture metadata on `RegExpObject` in the new representation.
Use the new API surface to simplify and speed up the builtin paths too:
share `exec_internal`, cache compiled regex pointers, keep the legacy
RegExp statics lazy, run global replace through batch `find_all`, and
optimize replace, test, split, and String helper paths. Add regression
tests for those JavaScript-visible paths.
2026-03-25 10:52:40 +01:00
legacy_static_properties . set_captures_lazy ( num_captures , capture_starts , capture_ends ) ;
}
2022-10-17 08:59:27 +08:00
// 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 ( ) ;
}
}