Explorar el Código

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

Timothy Flynn hace 4 años
padre
commit
5d11614bc7

+ 16 - 4
Userland/Libraries/LibJS/Runtime/StringPrototype.cpp

@@ -8,6 +8,7 @@
 #include <AK/Checked.h>
 #include <AK/Function.h>
 #include <AK/StringBuilder.h>
+#include <AK/Utf16View.h>
 #include <LibJS/Heap/Heap.h>
 #include <LibJS/Runtime/AbstractOperations.h>
 #include <LibJS/Runtime/Array.h>
@@ -31,6 +32,14 @@ static Optional<String> ak_string_from(VM& vm, GlobalObject& global_object)
     return this_value.to_string(global_object);
 }
 
+static Vector<u16> 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<size_t> 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

+ 8 - 0
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("");
+});