1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 14:37:46 +00:00

LibJS: Implement String.prototype.endsWith with UTF-16 code units

This commit is contained in:
Timothy Flynn 2021-07-19 16:01:35 -04:00 committed by Andreas Kling
parent d2e63a641f
commit bdbe716547
2 changed files with 25 additions and 14 deletions

View file

@ -304,8 +304,8 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::starts_with)
// 22.1.3.6 String.prototype.endsWith ( searchString [ , endPosition ] ), https://tc39.es/ecma262/#sec-string.prototype.endswith // 22.1.3.6 String.prototype.endsWith ( searchString [ , endPosition ] ), https://tc39.es/ecma262/#sec-string.prototype.endswith
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::ends_with) JS_DEFINE_NATIVE_FUNCTION(StringPrototype::ends_with)
{ {
auto string = ak_string_from(vm, global_object); auto string = utf16_string_from(vm, global_object);
if (!string.has_value()) if (vm.exception())
return {}; return {};
auto search_string_value = vm.argument(0); auto search_string_value = vm.argument(0);
@ -318,30 +318,33 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::ends_with)
return {}; return {};
} }
auto search_string = search_string_value.to_string(global_object); auto search_string = search_string_value.to_utf16_string(global_object);
if (vm.exception()) if (vm.exception())
return {}; return {};
auto string_length = string->length(); Utf16View utf16_string_view { string };
auto search_string_length = search_string.length(); auto string_length = utf16_string_view.length_in_code_units();
size_t pos = string_length; Utf16View utf16_search_view { search_string };
auto search_length = utf16_search_view.length_in_code_units();
auto end_position_value = vm.argument(1); size_t end = string_length;
if (!end_position_value.is_undefined()) { if (!vm.argument(1).is_undefined()) {
double pos_as_double = end_position_value.to_integer_or_infinity(global_object); auto position = vm.argument(1).to_integer_or_infinity(global_object);
if (vm.exception()) if (vm.exception())
return {}; return {};
pos = clamp(pos_as_double, static_cast<double>(0), static_cast<double>(string_length)); end = clamp(position, static_cast<double>(0), static_cast<double>(string_length));
} }
if (search_string_length == 0) if (search_length == 0)
return Value(true); return Value(true);
if (pos < search_string_length) if (search_length > end)
return Value(false); return Value(false);
auto start = pos - search_string_length; size_t start = end - search_length;
return Value(string->substring(start, search_string_length) == search_string);
utf16_string_view = utf16_string_view.substring_view(start, end - start);
return Value(utf16_string_view == utf16_search_view);
} }
// 22.1.3.8 String.prototype.indexOf ( searchString [ , position ] ), https://tc39.es/ecma262/#sec-string.prototype.indexof // 22.1.3.8 String.prototype.indexOf ( searchString [ , position ] ), https://tc39.es/ecma262/#sec-string.prototype.indexof

View file

@ -40,3 +40,11 @@ test("basic functionality", () => {
); );
expect(s.endsWith("bar", undefined)).toBeTrue(); expect(s.endsWith("bar", undefined)).toBeTrue();
}); });
test("UTF-16", () => {
var s = "😀";
expect(s.endsWith("😀")).toBeTrue();
expect(s.endsWith("\ud83d")).toBeFalse();
expect(s.endsWith("\ude00")).toBeTrue();
expect(s.endsWith("a")).toBeFalse();
});