mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 19:27:35 +00:00
LibJS: Implement ECMA-402 Array.prototype.toLocaleString
Turns out the only difference between our existing implementation and the ECMA-402 implementation is we weren't passing the locales and options list to each element.toLocaleString invocation. This also adds spec comments to the definition.
This commit is contained in:
parent
c19c3205ff
commit
39ab1a8999
2 changed files with 41 additions and 8 deletions
|
@ -388,9 +388,13 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_string)
|
|||
return TRY(vm.call(join_function.as_function(), this_object));
|
||||
}
|
||||
|
||||
// 23.1.3.30 Array.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] ), https://tc39.es/ecma262/#sec-array.prototype.tolocalestring
|
||||
// 18.5.1 Array.prototype.toLocaleString ( [ locales [ , options ] ] ), https://tc39.es/ecma402/#sup-array.prototype.tolocalestring
|
||||
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_locale_string)
|
||||
{
|
||||
auto locales = vm.argument(0);
|
||||
auto options = vm.argument(1);
|
||||
|
||||
// 1. Let array be ? ToObject(this value).
|
||||
auto* this_object = TRY(vm.this_value(global_object).to_object(global_object));
|
||||
|
||||
if (s_array_join_seen_objects.contains(this_object))
|
||||
|
@ -400,20 +404,41 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_locale_string)
|
|||
s_array_join_seen_objects.remove(this_object);
|
||||
};
|
||||
|
||||
// 2. Let len be ? ToLength(? Get(array, "length")).
|
||||
auto length = TRY(length_of_array_like(global_object, *this_object));
|
||||
|
||||
String separator = ","; // NOTE: This is implementation-specific.
|
||||
// 3. Let separator be the String value for the list-separator String appropriate for the host environment's current locale (this is derived in an implementation-defined way).
|
||||
constexpr auto separator = ","sv;
|
||||
|
||||
// 4. Let R be the empty String.
|
||||
StringBuilder builder;
|
||||
|
||||
// 5. Let k be 0.
|
||||
// 6. Repeat, while k < len,
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
if (i > 0)
|
||||
// a. If k > 0, then
|
||||
if (i > 0) {
|
||||
// i. Set R to the string-concatenation of R and separator.
|
||||
builder.append(separator);
|
||||
}
|
||||
|
||||
// b. Let nextElement be ? Get(array, ! ToString(k)).
|
||||
auto value = TRY(this_object->get(i));
|
||||
if (value.is_nullish())
|
||||
continue;
|
||||
auto locale_string_result = TRY(value.invoke(global_object, vm.names.toLocaleString));
|
||||
auto string = TRY(locale_string_result.to_string(global_object));
|
||||
builder.append(string);
|
||||
|
||||
// c. If nextElement is not undefined or null, then
|
||||
if (!value.is_nullish()) {
|
||||
// i. Let S be ? ToString(? Invoke(nextElement, "toLocaleString", « locales, options »)).
|
||||
auto locale_string_result = TRY(value.invoke(global_object, vm.names.toLocaleString, locales, options));
|
||||
|
||||
// ii. Set R to the string-concatenation of R and S.
|
||||
auto string = TRY(locale_string_result.to_string(global_object));
|
||||
builder.append(string);
|
||||
}
|
||||
|
||||
// d. Increase k by 1.
|
||||
}
|
||||
|
||||
// 7. Return R.
|
||||
return js_string(vm, builder.to_string());
|
||||
}
|
||||
|
||||
|
|
|
@ -59,4 +59,12 @@ describe("normal behavior", () => {
|
|||
// [ "foo", <circular>, [ 1, 2, <circular> ], [ "bar" ] ]
|
||||
expect(a.toLocaleString()).toBe("foo,,1,2,,bar");
|
||||
});
|
||||
|
||||
test("with options", () => {
|
||||
expect([12, 34].toLocaleString("en")).toBe("12");
|
||||
expect([12, 34].toLocaleString("ar")).toBe("\u0661\u0662,\u0663\u0664");
|
||||
|
||||
expect([0.234].toLocaleString("en", { style: "percent" })).toBe("23%");
|
||||
expect([0.234].toLocaleString("ar", { style: "percent" })).toBe("\u0662\u0663\u066a\u061c");
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue