mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 16:47:44 +00:00
LibJS: Implement String.prototype.toWellFormed
This commit is contained in:
parent
0bb46235a7
commit
3ee5217adc
4 changed files with 90 additions and 0 deletions
|
@ -526,6 +526,7 @@ namespace JS {
|
|||
P(toTimeString) \
|
||||
P(toUpperCase) \
|
||||
P(toUTCString) \
|
||||
P(toWellFormed) \
|
||||
P(toZonedDateTime) \
|
||||
P(toZonedDateTimeISO) \
|
||||
P(trace) \
|
||||
|
|
|
@ -171,6 +171,7 @@ void StringPrototype::initialize(Realm& realm)
|
|||
define_native_function(realm, vm.names.toLowerCase, to_lowercase, 0, attr);
|
||||
define_native_function(realm, vm.names.toString, to_string, 0, attr);
|
||||
define_native_function(realm, vm.names.toUpperCase, to_uppercase, 0, attr);
|
||||
define_native_function(realm, vm.names.toWellFormed, to_well_formed, 0, attr);
|
||||
define_native_function(realm, vm.names.trim, trim, 0, attr);
|
||||
define_native_function(realm, vm.names.trimEnd, trim_end, 0, attr);
|
||||
define_native_function(realm, vm.names.trimStart, trim_start, 0, attr);
|
||||
|
@ -980,6 +981,46 @@ JS_DEFINE_NATIVE_FUNCTION(StringPrototype::to_uppercase)
|
|||
return js_string(vm, move(uppercase));
|
||||
}
|
||||
|
||||
// 22.1.3.11 String.prototype.toWellFormed ( )
|
||||
JS_DEFINE_NATIVE_FUNCTION(StringPrototype::to_well_formed)
|
||||
{
|
||||
// 1. Let O be ? RequireObjectCoercible(this value).
|
||||
// 2. Let S be ? ToString(O).
|
||||
auto string = TRY(utf16_string_from(vm));
|
||||
|
||||
// 3. Let strLen be the length of S.
|
||||
auto length = string.length_in_code_units();
|
||||
|
||||
// 4. Let k be 0.
|
||||
size_t k = 0;
|
||||
|
||||
// 5. Let result be the empty String.
|
||||
StringBuilder result;
|
||||
|
||||
// 6. Repeat, while k < strLen,
|
||||
while (k < length) {
|
||||
// a. Let cp be CodePointAt(S, k).
|
||||
auto code_point = JS::code_point_at(string.view(), k);
|
||||
|
||||
// b. If cp.[[IsUnpairedSurrogate]] is true, then
|
||||
if (code_point.is_unpaired_surrogate) {
|
||||
// i. Set result to the string-concatenation of result and 0xFFFD (REPLACEMENT CHARACTER).
|
||||
result.append_code_point(0xfffd);
|
||||
}
|
||||
// c. Else,
|
||||
else {
|
||||
// i. Set result to the string-concatenation of result and UTF16EncodeCodePoint(cp.[[CodePoint]]).
|
||||
result.append_code_point(code_point.code_point);
|
||||
}
|
||||
|
||||
// d. Set k to k + cp.[[CodeUnitCount]].
|
||||
k += code_point.code_unit_count;
|
||||
}
|
||||
|
||||
// 7. Return result.
|
||||
return js_string(vm, result.build());
|
||||
}
|
||||
|
||||
ThrowCompletionOr<String> trim_string(VM& vm, Value input_value, TrimMode where)
|
||||
{
|
||||
// 1. Let str be ? RequireObjectCoercible(string).
|
||||
|
|
|
@ -59,6 +59,7 @@ private:
|
|||
JS_DECLARE_NATIVE_FUNCTION(to_lowercase);
|
||||
JS_DECLARE_NATIVE_FUNCTION(to_string);
|
||||
JS_DECLARE_NATIVE_FUNCTION(to_uppercase);
|
||||
JS_DECLARE_NATIVE_FUNCTION(to_well_formed);
|
||||
JS_DECLARE_NATIVE_FUNCTION(trim);
|
||||
JS_DECLARE_NATIVE_FUNCTION(trim_end);
|
||||
JS_DECLARE_NATIVE_FUNCTION(trim_start);
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
describe("errors", () => {
|
||||
test("called with value that cannot be converted to a string", () => {
|
||||
expect(() => {
|
||||
String.prototype.toWellFormed.call(Symbol.hasInstance);
|
||||
}).toThrowWithMessage(TypeError, "Cannot convert symbol to string");
|
||||
});
|
||||
});
|
||||
|
||||
describe("basic functionality", () => {
|
||||
test("ascii strings", () => {
|
||||
expect("".toWellFormed()).toBe("");
|
||||
expect("foo".toWellFormed()).toBe("foo");
|
||||
expect("abcdefghi".toWellFormed()).toBe("abcdefghi");
|
||||
});
|
||||
|
||||
test("valid UTF-16 strings", () => {
|
||||
expect("😀".toWellFormed()).toBe("😀");
|
||||
expect("\ud83d\ude00".toWellFormed()).toBe("\ud83d\ude00");
|
||||
});
|
||||
|
||||
test("invalid UTF-16 strings", () => {
|
||||
expect("😀".slice(0, 1).toWellFormed()).toBe("\ufffd");
|
||||
expect("😀".slice(1, 2).toWellFormed()).toBe("\ufffd");
|
||||
expect("\ud83d".toWellFormed()).toBe("\ufffd");
|
||||
expect("\ude00".toWellFormed()).toBe("\ufffd");
|
||||
expect("a\ud83d".toWellFormed()).toBe("a\ufffd");
|
||||
expect("a\ude00".toWellFormed()).toBe("a\ufffd");
|
||||
expect("\ud83da".toWellFormed()).toBe("\ufffda");
|
||||
expect("\ude00a".toWellFormed()).toBe("\ufffda");
|
||||
expect("a\ud83da".toWellFormed()).toBe("a\ufffda");
|
||||
expect("a\ude00a".toWellFormed()).toBe("a\ufffda");
|
||||
});
|
||||
|
||||
test("object converted to a string", () => {
|
||||
let toStringCalled = false;
|
||||
|
||||
const obj = {
|
||||
toString: function () {
|
||||
toStringCalled = true;
|
||||
return "toString";
|
||||
},
|
||||
};
|
||||
|
||||
expect(String.prototype.toWellFormed.call(obj)).toBe("toString");
|
||||
expect(toStringCalled).toBeTrue();
|
||||
});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue