diff --git a/Userland/Libraries/LibJS/Runtime/StringPrototype.cpp b/Userland/Libraries/LibJS/Runtime/StringPrototype.cpp index c7588b2f7f..3d837e167c 100644 --- a/Userland/Libraries/LibJS/Runtime/StringPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/StringPrototype.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +32,14 @@ static Optional ak_string_from(VM& vm, GlobalObject& global_object) return this_value.to_string(global_object); } +static Vector utf16_string_from(VM& vm, GlobalObject& global_object) +{ + auto this_value = require_object_coercible(global_object, vm.this_value(global_object)); + if (vm.exception()) + return {}; + return this_value.to_utf16_string(global_object); +} + static Optional split_match(const String& haystack, size_t start, const String& needle) { auto r = needle.length(); @@ -119,15 +128,18 @@ static Value this_string_value(GlobalObject& global_object, Value value) // 22.1.3.1 String.prototype.charAt ( pos ), https://tc39.es/ecma262/#sec-string.prototype.charat JS_DEFINE_NATIVE_FUNCTION(StringPrototype::char_at) { - auto string = ak_string_from(vm, global_object); - if (!string.has_value()) + auto string = utf16_string_from(vm, global_object); + if (vm.exception()) return {}; auto position = vm.argument(0).to_integer_or_infinity(global_object); if (vm.exception()) return {}; - if (position < 0 || position >= string->length()) + + Utf16View utf16_string_view { string }; + if (position < 0 || position >= utf16_string_view.length_in_code_units()) return js_string(vm, String::empty()); - return js_string(vm, string->substring(position, 1)); + + return js_string(vm, utf16_string_view.substring_view(position, 1)); } // 22.1.3.2 String.prototype.charCodeAt ( pos ), https://tc39.es/ecma262/#sec-string.prototype.charcodeat diff --git a/Userland/Libraries/LibJS/Tests/builtins/String/String.prototype.charAt.js b/Userland/Libraries/LibJS/Tests/builtins/String/String.prototype.charAt.js index 7747331885..c1b1779906 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/String/String.prototype.charAt.js +++ b/Userland/Libraries/LibJS/Tests/builtins/String/String.prototype.charAt.js @@ -18,3 +18,11 @@ test("basic functionality", () => { expect(s.charAt("foo")).toBe("f"); expect(s.charAt(undefined)).toBe("f"); }); + +test("UTF-16", () => { + var s = "😀"; + expect(s).toHaveLength(2); + expect(s.charAt(0)).toBe("\ud83d"); + expect(s.charAt(1)).toBe("\ude00"); + expect(s.charAt(2)).toBe(""); +});