mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 11:57: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));
|
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)
|
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));
|
auto* this_object = TRY(vm.this_value(global_object).to_object(global_object));
|
||||||
|
|
||||||
if (s_array_join_seen_objects.contains(this_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);
|
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));
|
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;
|
StringBuilder builder;
|
||||||
|
|
||||||
|
// 5. Let k be 0.
|
||||||
|
// 6. Repeat, while k < len,
|
||||||
for (size_t i = 0; i < length; ++i) {
|
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);
|
builder.append(separator);
|
||||||
|
}
|
||||||
|
|
||||||
|
// b. Let nextElement be ? Get(array, ! ToString(k)).
|
||||||
auto value = TRY(this_object->get(i));
|
auto value = TRY(this_object->get(i));
|
||||||
if (value.is_nullish())
|
|
||||||
continue;
|
// c. If nextElement is not undefined or null, then
|
||||||
auto locale_string_result = TRY(value.invoke(global_object, vm.names.toLocaleString));
|
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));
|
auto string = TRY(locale_string_result.to_string(global_object));
|
||||||
builder.append(string);
|
builder.append(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// d. Increase k by 1.
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7. Return R.
|
||||||
return js_string(vm, builder.to_string());
|
return js_string(vm, builder.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,4 +59,12 @@ describe("normal behavior", () => {
|
||||||
// [ "foo", <circular>, [ 1, 2, <circular> ], [ "bar" ] ]
|
// [ "foo", <circular>, [ 1, 2, <circular> ], [ "bar" ] ]
|
||||||
expect(a.toLocaleString()).toBe("foo,,1,2,,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