mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 11:57:35 +00:00
LibJS: Implement String.prototype.substring with UTF-16 code units
This commit is contained in:
parent
767700d8a1
commit
60d8852fc2
2 changed files with 23 additions and 21 deletions
|
@ -497,40 +497,31 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::concat)
|
||||||
// 22.1.3.23 String.prototype.substring ( start, end ), https://tc39.es/ecma262/#sec-string.prototype.substring
|
// 22.1.3.23 String.prototype.substring ( start, end ), https://tc39.es/ecma262/#sec-string.prototype.substring
|
||||||
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::substring)
|
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::substring)
|
||||||
{
|
{
|
||||||
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 {};
|
||||||
if (vm.argument_count() == 0)
|
|
||||||
return js_string(vm, *string);
|
|
||||||
|
|
||||||
// FIXME: index_start and index_end should index a UTF-16 code_point view of the string.
|
Utf16View utf16_string_view { string };
|
||||||
auto string_length = string->length();
|
auto string_length = static_cast<double>(utf16_string_view.length_in_code_units());
|
||||||
|
|
||||||
auto start = vm.argument(0).to_integer_or_infinity(global_object);
|
auto start = vm.argument(0).to_integer_or_infinity(global_object);
|
||||||
if (vm.exception())
|
if (vm.exception())
|
||||||
return {};
|
return {};
|
||||||
auto end = (double)string_length;
|
|
||||||
|
auto end = string_length;
|
||||||
if (!vm.argument(1).is_undefined()) {
|
if (!vm.argument(1).is_undefined()) {
|
||||||
end = vm.argument(1).to_integer_or_infinity(global_object);
|
end = vm.argument(1).to_integer_or_infinity(global_object);
|
||||||
if (vm.exception())
|
if (vm.exception())
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
size_t index_start = clamp(start, static_cast<double>(0), static_cast<double>(string_length));
|
|
||||||
size_t index_end = clamp(end, static_cast<double>(0), static_cast<double>(string_length));
|
|
||||||
|
|
||||||
if (index_start == index_end)
|
size_t final_start = clamp(start, static_cast<double>(0), string_length);
|
||||||
return js_string(vm, String(""));
|
size_t final_end = clamp(end, static_cast<double>(0), string_length);
|
||||||
|
|
||||||
if (index_start > index_end) {
|
size_t from = min(final_start, final_end);
|
||||||
if (vm.argument_count() == 1)
|
size_t to = max(final_start, final_end);
|
||||||
return js_string(vm, String(""));
|
|
||||||
auto temp_index_start = index_start;
|
|
||||||
index_start = index_end;
|
|
||||||
index_end = temp_index_start;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto part_length = index_end - index_start;
|
return js_string(vm, utf16_string_view.substring_view(from, to - from));
|
||||||
auto string_part = string->substring(index_start, part_length);
|
|
||||||
return js_string(vm, string_part);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// B.2.3.1 String.prototype.substr ( start, length ), https://tc39.es/ecma262/#sec-string.prototype.substr
|
// B.2.3.1 String.prototype.substr ( start, length ), https://tc39.es/ecma262/#sec-string.prototype.substr
|
||||||
|
|
|
@ -12,3 +12,14 @@ test("basic functionality", () => {
|
||||||
expect("hello friends".substring(0, "5")).toBe("hello");
|
expect("hello friends".substring(0, "5")).toBe("hello");
|
||||||
expect("hello friends".substring("6", "13")).toBe("friends");
|
expect("hello friends".substring("6", "13")).toBe("friends");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("UTF-16", () => {
|
||||||
|
var s = "😀";
|
||||||
|
expect(s).toHaveLength(2);
|
||||||
|
expect(s.substring()).toBe("😀");
|
||||||
|
expect(s.substring(0)).toBe("😀");
|
||||||
|
expect(s.substring(0, 2)).toBe("😀");
|
||||||
|
expect(s.substring(0, 1)).toBe("\ud83d");
|
||||||
|
expect(s.substring(1, 2)).toBe("\ude00");
|
||||||
|
expect(s.substring(2, 2)).toBe("");
|
||||||
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue