diff --git a/Userland/Libraries/LibJS/CMakeLists.txt b/Userland/Libraries/LibJS/CMakeLists.txt index 344f0d2864..17967c78a5 100644 --- a/Userland/Libraries/LibJS/CMakeLists.txt +++ b/Userland/Libraries/LibJS/CMakeLists.txt @@ -165,4 +165,4 @@ set(SOURCES ) serenity_lib(LibJS js) -target_link_libraries(LibJS LibM LibCore LibCrypto LibRegex LibSyntax) +target_link_libraries(LibJS LibM LibCore LibCrypto LibRegex LibSyntax LibUnicode) diff --git a/Userland/Libraries/LibJS/Runtime/StringPrototype.cpp b/Userland/Libraries/LibJS/Runtime/StringPrototype.cpp index 7ce3d70df7..08e3ea63d8 100644 --- a/Userland/Libraries/LibJS/Runtime/StringPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/StringPrototype.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include namespace JS { @@ -380,21 +381,33 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::index_of) // 22.1.3.26 String.prototype.toLowerCase ( ), https://tc39.es/ecma262/#sec-string.prototype.tolowercase JS_DEFINE_NATIVE_FUNCTION(StringPrototype::to_lowercase) { - // FIXME: Implement Unicode case folding: https://www.unicode.org/Public/13.0.0/ucd/CaseFolding.txt - auto string = ak_string_from(vm, global_object); - if (!string.has_value()) + auto string = utf16_string_from(vm, global_object); + if (vm.exception()) return {}; - return js_string(vm, string->to_lowercase()); + + Utf16View utf16_string_view { string }; + StringBuilder builder; + + for (auto code_point : utf16_string_view) + builder.append_code_point(Unicode::to_unicode_lowercase(code_point)); + + return js_string(vm, builder.to_string()); } // 22.1.3.28 String.prototype.toUpperCase ( ), https://tc39.es/ecma262/#sec-string.prototype.touppercase JS_DEFINE_NATIVE_FUNCTION(StringPrototype::to_uppercase) { - // FIXME: Implement Unicode case folding: https://www.unicode.org/Public/13.0.0/ucd/CaseFolding.txt - auto string = ak_string_from(vm, global_object); - if (!string.has_value()) + auto string = utf16_string_from(vm, global_object); + if (vm.exception()) return {}; - return js_string(vm, string->to_uppercase()); + + Utf16View utf16_string_view { string }; + StringBuilder builder; + + for (auto code_point : utf16_string_view) + builder.append_code_point(Unicode::to_unicode_uppercase(code_point)); + + return js_string(vm, builder.to_string()); } // 22.1.3.27 String.prototype.toString ( ), https://tc39.es/ecma262/#sec-string.prototype.tostring diff --git a/Userland/Libraries/LibJS/Tests/builtins/String/String.prototype.toLowerCase.js b/Userland/Libraries/LibJS/Tests/builtins/String/String.prototype.toLowerCase.js index 4c7cbad50a..da176af6d8 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/String/String.prototype.toLowerCase.js +++ b/Userland/Libraries/LibJS/Tests/builtins/String/String.prototype.toLowerCase.js @@ -1,6 +1,10 @@ test("basic functionality", () => { expect(String.prototype.toLowerCase).toHaveLength(0); + expect("ω".toLowerCase()).toBe("ω"); + expect("Ω".toLowerCase()).toBe("ω"); + expect("😀".toLowerCase()).toBe("😀"); + expect("foo".toLowerCase()).toBe("foo"); expect("Foo".toLowerCase()).toBe("foo"); expect("FOO".toLowerCase()).toBe("foo"); diff --git a/Userland/Libraries/LibJS/Tests/builtins/String/String.prototype.toUpperCase.js b/Userland/Libraries/LibJS/Tests/builtins/String/String.prototype.toUpperCase.js index 03f463c6e1..51526733c8 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/String/String.prototype.toUpperCase.js +++ b/Userland/Libraries/LibJS/Tests/builtins/String/String.prototype.toUpperCase.js @@ -1,6 +1,10 @@ test("basic functionality", () => { expect(String.prototype.toUpperCase).toHaveLength(0); + expect("ω".toUpperCase()).toBe("Ω"); + expect("Ω".toUpperCase()).toBe("Ω"); + expect("😀".toUpperCase()).toBe("😀"); + expect("foo".toUpperCase()).toBe("FOO"); expect("Foo".toUpperCase()).toBe("FOO"); expect("FOO".toUpperCase()).toBe("FOO");