From 2dc9ae00af130968af1f98cff4c39bf017149676 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Tue, 27 Jul 2021 14:02:47 -0400 Subject: [PATCH] LibJS: Use special case folding for String.prototype.to{Lower,Upper}Case Note we still have one String.prototype.toLowerCase test262 failure due to not yet parsing WordBreakProperty.txt. --- .../LibJS/Runtime/StringPrototype.cpp | 26 ++++++------------- .../String/String.prototype.toLowerCase.js | 15 +++++++++++ .../String/String.prototype.toUpperCase.js | 17 ++++++++++++ 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/Userland/Libraries/LibJS/Runtime/StringPrototype.cpp b/Userland/Libraries/LibJS/Runtime/StringPrototype.cpp index 08e3ea63d8..fcbde841cb 100644 --- a/Userland/Libraries/LibJS/Runtime/StringPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/StringPrototype.cpp @@ -381,33 +381,23 @@ 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) { - auto string = utf16_string_from(vm, global_object); - if (vm.exception()) + auto string = ak_string_from(vm, global_object); + if (!string.has_value()) return {}; - 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()); + auto lowercase = Unicode::to_unicode_lowercase_full(*string); + return js_string(vm, move(lowercase)); } // 22.1.3.28 String.prototype.toUpperCase ( ), https://tc39.es/ecma262/#sec-string.prototype.touppercase JS_DEFINE_NATIVE_FUNCTION(StringPrototype::to_uppercase) { - auto string = utf16_string_from(vm, global_object); - if (vm.exception()) + auto string = ak_string_from(vm, global_object); + if (!string.has_value()) return {}; - 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()); + auto uppercase = Unicode::to_unicode_uppercase_full(*string); + return js_string(vm, move(uppercase)); } // 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 da176af6d8..bf3cc754d5 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/String/String.prototype.toLowerCase.js +++ b/Userland/Libraries/LibJS/Tests/builtins/String/String.prototype.toLowerCase.js @@ -11,3 +11,18 @@ test("basic functionality", () => { expect(("b" + "a" + +"a" + "a").toLowerCase()).toBe("banana"); }); + +test("special case folding", () => { + expect("\u00DF".toLowerCase()).toBe("\u00DF"); + expect("\u0130".toLowerCase()).toBe("\u0069\u0307"); + expect("\uFB00".toLowerCase()).toBe("\uFB00"); + expect("\uFB01".toLowerCase()).toBe("\uFB01"); + expect("\uFB02".toLowerCase()).toBe("\uFB02"); + expect("\uFB03".toLowerCase()).toBe("\uFB03"); + expect("\uFB04".toLowerCase()).toBe("\uFB04"); + expect("\uFB05".toLowerCase()).toBe("\uFB05"); + expect("\uFB06".toLowerCase()).toBe("\uFB06"); + expect("\u1FB7".toLowerCase()).toBe("\u1FB7"); + expect("\u1FC7".toLowerCase()).toBe("\u1FC7"); + expect("\u1FF7".toLowerCase()).toBe("\u1FF7"); +}); 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 51526733c8..42631a4112 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/String/String.prototype.toUpperCase.js +++ b/Userland/Libraries/LibJS/Tests/builtins/String/String.prototype.toUpperCase.js @@ -11,3 +11,20 @@ test("basic functionality", () => { expect(("b" + "a" + +"n" + "a").toUpperCase()).toBe("BANANA"); }); + +test("special case folding", () => { + expect("\u00DF".toUpperCase()).toBe("\u0053\u0053"); + expect("\u0130".toUpperCase()).toBe("\u0130"); + expect("\uFB00".toUpperCase()).toBe("\u0046\u0046"); + expect("\uFB01".toUpperCase()).toBe("\u0046\u0049"); + expect("\uFB02".toUpperCase()).toBe("\u0046\u004C"); + expect("\uFB03".toUpperCase()).toBe("\u0046\u0046\u0049"); + expect("\uFB04".toUpperCase()).toBe("\u0046\u0046\u004C"); + expect("\uFB05".toUpperCase()).toBe("\u0053\u0054"); + expect("\uFB06".toUpperCase()).toBe("\u0053\u0054"); + expect("\u0390".toUpperCase()).toBe("\u0399\u0308\u0301"); + expect("\u03B0".toUpperCase()).toBe("\u03A5\u0308\u0301"); + expect("\u1FB7".toUpperCase()).toBe("\u0391\u0342\u0399"); + expect("\u1FC7".toUpperCase()).toBe("\u0397\u0342\u0399"); + expect("\u1FF7".toUpperCase()).toBe("\u03A9\u0342\u0399"); +});