mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-20 01:37:39 +03:00
LibJS: Add spec comments to RegExp.prototype [ @@split ]
In doing so, this caught another erroneous ToObject invocation.
This commit is contained in:
parent
cb901f70af
commit
c6e2b03073
Notes:
sideshowbarker
2024-07-17 22:30:38 +09:00
Author: https://github.com/trflynn89 Commit: https://github.com/SerenityOS/serenity/commit/c6e2b03073c Pull-request: https://github.com/SerenityOS/serenity/pull/11334 Reviewed-by: https://github.com/davidot ✅ Reviewed-by: https://github.com/linusg ✅
@ -703,87 +703,157 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_search)
|
|||||||
// 22.2.5.13 RegExp.prototype [ @@split ] ( string, limit ), https://tc39.es/ecma262/#sec-regexp.prototype-@@split
|
// 22.2.5.13 RegExp.prototype [ @@split ] ( string, limit ), https://tc39.es/ecma262/#sec-regexp.prototype-@@split
|
||||||
JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_split)
|
JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_split)
|
||||||
{
|
{
|
||||||
|
// 1. Let rx be the this value.
|
||||||
|
// 2. If Type(rx) is not Object, throw a TypeError exception.
|
||||||
auto* regexp_object = TRY(this_object(global_object));
|
auto* regexp_object = TRY(this_object(global_object));
|
||||||
auto string = TRY(vm.argument(0).to_utf16_string(global_object));
|
|
||||||
auto string_view = string.view();
|
|
||||||
|
|
||||||
|
// 3. Let S be ? ToString(string).
|
||||||
|
auto string = TRY(vm.argument(0).to_utf16_string(global_object));
|
||||||
|
|
||||||
|
// 4. Let C be ? SpeciesConstructor(rx, %RegExp%).
|
||||||
auto* constructor = TRY(species_constructor(global_object, *regexp_object, *global_object.regexp_constructor()));
|
auto* constructor = TRY(species_constructor(global_object, *regexp_object, *global_object.regexp_constructor()));
|
||||||
|
|
||||||
|
// 5. Let flags be ? ToString(? Get(rx, "flags")).
|
||||||
auto flags_value = TRY(regexp_object->get(vm.names.flags));
|
auto flags_value = TRY(regexp_object->get(vm.names.flags));
|
||||||
auto flags = TRY(flags_value.to_string(global_object));
|
auto flags = TRY(flags_value.to_string(global_object));
|
||||||
|
|
||||||
bool unicode = flags.find('u').has_value();
|
// 6. If flags contains "u", let unicodeMatching be true.
|
||||||
|
// 7. Else, let unicodeMatching be false.
|
||||||
|
bool unicode_matching = flags.find('u').has_value();
|
||||||
|
|
||||||
|
// 8. If flags contains "y", let newFlags be flags.
|
||||||
|
// 9. Else, let newFlags be the string-concatenation of flags and "y".
|
||||||
auto new_flags = flags.find('y').has_value() ? move(flags) : String::formatted("{}y", flags);
|
auto new_flags = flags.find('y').has_value() ? move(flags) : String::formatted("{}y", flags);
|
||||||
|
|
||||||
|
// 10. Let splitter be ? Construct(C, « rx, newFlags »).
|
||||||
MarkedValueList arguments(vm.heap());
|
MarkedValueList arguments(vm.heap());
|
||||||
arguments.append(regexp_object);
|
arguments.append(regexp_object);
|
||||||
arguments.append(js_string(vm, move(new_flags)));
|
arguments.append(js_string(vm, move(new_flags)));
|
||||||
auto* splitter = TRY(construct(global_object, *constructor, move(arguments)));
|
auto* splitter = TRY(construct(global_object, *constructor, move(arguments)));
|
||||||
|
|
||||||
|
// 11. Let A be ! ArrayCreate(0).
|
||||||
auto* array = MUST(Array::create(global_object, 0));
|
auto* array = MUST(Array::create(global_object, 0));
|
||||||
|
|
||||||
|
// 12. Let lengthA be 0.
|
||||||
size_t array_length = 0;
|
size_t array_length = 0;
|
||||||
|
|
||||||
|
// 13. If limit is undefined, let lim be 2^32 - 1; else let lim be ℝ(? ToUint32(limit)).
|
||||||
auto limit = NumericLimits<u32>::max();
|
auto limit = NumericLimits<u32>::max();
|
||||||
if (!vm.argument(1).is_undefined())
|
if (!vm.argument(1).is_undefined())
|
||||||
limit = TRY(vm.argument(1).to_u32(global_object));
|
limit = TRY(vm.argument(1).to_u32(global_object));
|
||||||
|
|
||||||
|
// 14. If lim is 0, return A.
|
||||||
if (limit == 0)
|
if (limit == 0)
|
||||||
return array;
|
return array;
|
||||||
|
|
||||||
|
// 15. Let size be the length of S.
|
||||||
|
// 16. If size is 0, then
|
||||||
if (string.is_empty()) {
|
if (string.is_empty()) {
|
||||||
|
// a. Let z be ? RegExpExec(splitter, S).
|
||||||
auto result = TRY(regexp_exec(global_object, *splitter, string));
|
auto result = TRY(regexp_exec(global_object, *splitter, string));
|
||||||
|
|
||||||
|
// b. If z is not null, return A.
|
||||||
if (!result.is_null())
|
if (!result.is_null())
|
||||||
return array;
|
return array;
|
||||||
|
|
||||||
|
// c. Perform ! CreateDataPropertyOrThrow(A, "0", S).
|
||||||
MUST(array->create_data_property_or_throw(0, js_string(vm, move(string))));
|
MUST(array->create_data_property_or_throw(0, js_string(vm, move(string))));
|
||||||
|
|
||||||
|
// d. Return A.
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t last_match_end = 0; // 'p' in the spec.
|
// 17. Let p be 0.
|
||||||
size_t next_search_from = 0; // 'q' in the spec.
|
size_t last_match_end = 0;
|
||||||
|
|
||||||
while (next_search_from < string_view.length_in_code_units()) {
|
// 18. Let q be p.
|
||||||
|
size_t next_search_from = 0;
|
||||||
|
|
||||||
|
// 19. Repeat, while q < size,
|
||||||
|
while (next_search_from < string.length_in_code_units()) {
|
||||||
|
// a. Perform ? Set(splitter, "lastIndex", 𝔽(q), true).
|
||||||
TRY(splitter->set(vm.names.lastIndex, Value(next_search_from), Object::ShouldThrowExceptions::Yes));
|
TRY(splitter->set(vm.names.lastIndex, Value(next_search_from), Object::ShouldThrowExceptions::Yes));
|
||||||
|
|
||||||
|
// b. Let z be ? RegExpExec(splitter, S).
|
||||||
auto result = TRY(regexp_exec(global_object, *splitter, string));
|
auto result = TRY(regexp_exec(global_object, *splitter, string));
|
||||||
|
|
||||||
|
// c. If z is null, set q to AdvanceStringIndex(S, q, unicodeMatching).
|
||||||
if (result.is_null()) {
|
if (result.is_null()) {
|
||||||
next_search_from = advance_string_index(string_view, next_search_from, unicode);
|
next_search_from = advance_string_index(string.view(), next_search_from, unicode_matching);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// d. Else,
|
||||||
|
|
||||||
|
// i. Let e be ℝ(? ToLength(? Get(splitter, "lastIndex"))).
|
||||||
auto last_index_value = TRY(splitter->get(vm.names.lastIndex));
|
auto last_index_value = TRY(splitter->get(vm.names.lastIndex));
|
||||||
auto last_index = TRY(last_index_value.to_length(global_object)); // 'e' in the spec.
|
auto last_index = TRY(last_index_value.to_length(global_object));
|
||||||
last_index = min(last_index, string_view.length_in_code_units());
|
|
||||||
|
|
||||||
|
// ii. Set e to min(e, size).
|
||||||
|
last_index = min(last_index, string.length_in_code_units());
|
||||||
|
|
||||||
|
// iii. If e = p, set q to AdvanceStringIndex(S, q, unicodeMatching).
|
||||||
if (last_index == last_match_end) {
|
if (last_index == last_match_end) {
|
||||||
next_search_from = advance_string_index(string_view, next_search_from, unicode);
|
next_search_from = advance_string_index(string.view(), next_search_from, unicode_matching);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto substring = string_view.substring_view(last_match_end, next_search_from - last_match_end);
|
// iv. Else,
|
||||||
MUST(array->create_data_property_or_throw(array_length, js_string(vm, move(substring))));
|
|
||||||
|
|
||||||
if (++array_length == limit)
|
// 1. Let T be the substring of S from p to q.
|
||||||
|
auto substring = string.substring_view(last_match_end, next_search_from - last_match_end);
|
||||||
|
|
||||||
|
// 2. Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(lengthA)), T).
|
||||||
|
MUST(array->create_data_property_or_throw(array_length, js_string(vm, substring)));
|
||||||
|
|
||||||
|
// 3. Set lengthA to lengthA + 1.
|
||||||
|
++array_length;
|
||||||
|
|
||||||
|
// 4. If lengthA = lim, return A.
|
||||||
|
if (array_length == limit)
|
||||||
return array;
|
return array;
|
||||||
|
|
||||||
auto* result_object = TRY(result.to_object(global_object));
|
// 5. Set p to e.
|
||||||
auto number_of_captures = TRY(length_of_array_like(global_object, *result_object));
|
last_match_end = last_index;
|
||||||
|
|
||||||
|
// 6. Let numberOfCaptures be ? LengthOfArrayLike(z).
|
||||||
|
auto number_of_captures = TRY(length_of_array_like(global_object, result.as_object()));
|
||||||
|
|
||||||
|
// 7. Set numberOfCaptures to max(numberOfCaptures - 1, 0).
|
||||||
if (number_of_captures > 0)
|
if (number_of_captures > 0)
|
||||||
--number_of_captures;
|
--number_of_captures;
|
||||||
|
|
||||||
|
// 8. Let i be 1.
|
||||||
|
// 9. Repeat, while i ≤ numberOfCaptures,
|
||||||
for (size_t i = 1; i <= number_of_captures; ++i) {
|
for (size_t i = 1; i <= number_of_captures; ++i) {
|
||||||
auto next_capture = TRY(result_object->get(i));
|
|
||||||
|
// a. Let nextCapture be ? Get(z, ! ToString(𝔽(i))).
|
||||||
|
auto next_capture = TRY(result.get(global_object, i));
|
||||||
|
|
||||||
|
// b. Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(lengthA)), nextCapture).
|
||||||
MUST(array->create_data_property_or_throw(array_length, next_capture));
|
MUST(array->create_data_property_or_throw(array_length, next_capture));
|
||||||
if (++array_length == limit)
|
|
||||||
|
// c. Set i to i + 1.
|
||||||
|
|
||||||
|
// d. Set lengthA to lengthA + 1.
|
||||||
|
++array_length;
|
||||||
|
|
||||||
|
// e. If lengthA = lim, return A.
|
||||||
|
if (array_length == limit)
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
last_match_end = last_index;
|
// 10. Set q to p.
|
||||||
next_search_from = last_index;
|
next_search_from = last_match_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto substring = string_view.substring_view(last_match_end);
|
// 20. Let T be the substring of S from p to size.
|
||||||
MUST(array->create_data_property_or_throw(array_length, js_string(vm, move(substring))));
|
auto substring = string.substring_view(last_match_end);
|
||||||
|
|
||||||
|
// 21. Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(lengthA)), T).
|
||||||
|
MUST(array->create_data_property_or_throw(array_length, js_string(vm, substring)));
|
||||||
|
|
||||||
|
// 22. Return A.
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user