Skip to content
Open
5 changes: 4 additions & 1 deletion core/engine/src/builtins/intl/number_format/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -761,7 +761,10 @@ fn unwrap_number_format(nf: &JsValue, context: &mut Context) -> JsResult<JsObjec
/// Abstract operation [`ToIntlMathematicalValue ( value )`][spec].
///
/// [spec]: https://tc39.es/ecma402/#sec-tointlmathematicalvalue
fn to_intl_mathematical_value(value: &JsValue, context: &mut Context) -> JsResult<Decimal> {
pub(crate) fn to_intl_mathematical_value(
value: &JsValue,
context: &mut Context,
) -> JsResult<Decimal> {
// 1. Let primValue be ? ToPrimitive(value, number).
let prim_value = value.to_primitive(context, PreferredType::Number)?;

Expand Down
19 changes: 18 additions & 1 deletion core/engine/src/builtins/number/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,19 @@ pub(crate) struct Number;

impl IntrinsicObject for Number {
fn init(realm: &Realm) {
let to_locale_string_function = BuiltInBuilder::callable_with_object(
realm,
realm
.intrinsics()
.objects()
.number_prototype_to_locale_string()
.into(),
Self::to_locale_string,
)
.name(js_string!("toLocaleString"))
.length(0)
.build();

let attribute = Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::PERMANENT;

BuiltInBuilder::from_standard_constructor::<Self>(realm)
Expand Down Expand Up @@ -87,7 +100,11 @@ impl IntrinsicObject for Number {
.static_method(Self::number_is_integer, js_string!("isInteger"), 1)
.method(Self::to_exponential, js_string!("toExponential"), 1)
.method(Self::to_fixed, js_string!("toFixed"), 1)
.method(Self::to_locale_string, js_string!("toLocaleString"), 0)
.property(
js_string!("toLocaleString"),
to_locale_string_function,
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
)
.method(Self::to_precision, js_string!("toPrecision"), 1)
.method(Self::to_string, js_string!("toString"), 1)
.method(Self::value_of, js_string!("valueOf"), 0)
Expand Down
38 changes: 27 additions & 11 deletions core/engine/src/builtins/typed_array/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use std::{
sync::atomic::Ordering,
};

use boa_macros::utf16;
use num_traits::Zero;

use super::{
Expand Down Expand Up @@ -1209,7 +1208,7 @@ impl BuiltinTypedArray {
};

// 6. Let R be the empty String.
let mut r = Vec::new();
let mut r = Vec::with_capacity(len as usize);

// 7. Let k be 0.
// 8. Repeat, while k < len,
Expand Down Expand Up @@ -2501,24 +2500,44 @@ impl BuiltinTypedArray {
(o.array_length(buf_len), is_fixed_len)
};

let locales = args.get_or_undefined(0);
let options = args.get_or_undefined(1);

let separator = {
#[cfg(feature = "intl")]
{
// TODO: this should eventually return a locale-sensitive separator.
utf16!(", ")
use crate::builtins::intl::locale::default_locale;
use icu_list::{
ListFormatter, ListFormatterPreferences, options::ListFormatterOptions,
};

let locale = default_locale(context.intl_provider().locale_canonicalizer()?);
let preferences = ListFormatterPreferences::from(&locale);
let formatter = ListFormatter::try_new_unit_with_buffer_provider(
context.intl_provider().erased_provider(),
preferences,
ListFormatterOptions::default(),
)
.map_err(|e| JsNativeError::typ().with_message(e.to_string()))?;

// Ask ICU for the list pattern literal by formatting two empty elements.
// For many locales this yields ", ", but it may differ.
js_string!(
formatter.format_to_string(std::iter::once("").chain(std::iter::once("")))
)
}

#[cfg(not(feature = "intl"))]
{
utf16!(", ")
js_string!(", ")
}
};

let mut r = Vec::new();
let mut r = Vec::with_capacity((len + len.saturating_sub(1)) as usize);

for k in 0..len {
if k > 0 {
r.extend_from_slice(separator);
r.extend(separator.iter());
}

let next_element = array.get(k, context)?;
Expand All @@ -2529,10 +2548,7 @@ impl BuiltinTypedArray {
let s = next_element
.invoke(
js_string!("toLocaleString"),
&[
args.get_or_undefined(0).clone(),
args.get_or_undefined(1).clone(),
],
&[locales.clone(), options.clone()],
context,
)?
.to_string(context)?;
Expand Down
13 changes: 13 additions & 0 deletions core/engine/src/context/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1086,6 +1086,9 @@ pub struct IntrinsicObjects {
/// [`%Array.prototype.toString%`](https://tc39.es/ecma262/#sec-array.prototype.tostring)
array_prototype_to_string: JsFunction,

/// [`%Number.prototype.toLocaleString%`](https://tc39.es/ecma262/#sec-number.prototype.tolocalestring)
number_prototype_to_locale_string: JsFunction,

/// Cached iterator prototypes.
iterator_prototypes: IteratorPrototypes,

Expand Down Expand Up @@ -1158,6 +1161,7 @@ impl IntrinsicObjects {
throw_type_error: JsFunction::empty_intrinsic_function(false),
array_prototype_values: JsFunction::empty_intrinsic_function(false),
array_prototype_to_string: JsFunction::empty_intrinsic_function(false),
number_prototype_to_locale_string: JsFunction::empty_intrinsic_function(false),
iterator_prototypes: IteratorPrototypes::default(),
generator: JsObject::with_null_proto(),
async_generator: JsObject::with_null_proto(),
Expand Down Expand Up @@ -1210,6 +1214,15 @@ impl IntrinsicObjects {
self.array_prototype_to_string.clone()
}

/// Gets the [`%Number.prototype.toLocaleString%`][spec] intrinsic function.
///
/// [spec]: https://tc39.es/ecma262/#sec-number.prototype.tolocalestring
#[inline]
#[must_use]
pub fn number_prototype_to_locale_string(&self) -> JsFunction {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need this anymore since the changes were reverted

self.number_prototype_to_locale_string.clone()
}

/// Gets the cached iterator prototypes.
#[inline]
#[must_use]
Expand Down
Loading