From 4ca14d38a8d9209a6c84f8b3fa77c1ee8ebcb861 Mon Sep 17 00:00:00 2001 From: Jesse Alama Date: Wed, 12 Nov 2025 19:23:46 +0100 Subject: [PATCH 1/4] Adapt `ToIntlMathematicalValue` to handle initial numeric-like text --- intl.emu | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/intl.emu b/intl.emu index 4f3d209..7db93d5 100644 --- a/intl.emu +++ b/intl.emu @@ -27,9 +27,16 @@ 1. Let _O_ be the *this* value. - 1. Perform ? RequireInternalSlot(_O_, [[Decimal128Data]]). + 1. Perform ? RequireInternalSlot(_O_, [[Value]]). + 1. Let _amountUnit_ be _O_.[[Unit]]. + 1. Let _optionsUnit_ be _options_.[[unit]]. + 1. If _amountUnit_ is a String, then + 1. If _optionsUnit_ is a String, then + 1. If _amountUnit_ is not equal to _optionsUnit_, throw a *TypeError* exception. + 1. Else, + 1. Set _options_.[[unit]] to _amountUnit_. 1. Let _numberFormat_ be ? Construct(%Intl.NumberFormat%, « _locales_, _options_ »). - 1. Return FormatNumeric(_numberFormat_, _O_.[[AmountData]]). + 1. Return FormatNumeric(_numberFormat_, _O_.[[Value]]). @@ -152,7 +159,7 @@ - 1. If _value_ has the [[Value]] and [[FractionDigits]] internal slots, let _primValue_ be RenderAmountValueWithFractionDigits(_value_.[[Value]], _value_.[[FractionDigits]]) elseLet let~number~~string~). 1. If _primValue_ is a BigInt, return ℝ(_primValue_). 1. If _primValue_ is a String, then 1. Let _str_ be _primValue_. @@ -161,8 +168,10 @@ 1. If _x_ is *-0*𝔽, return ~negative-zero~. 1. Let _str_ be Number::toString(_x_, 10). 1. Let _text_ be StringToCodePoints(_str_). - 1. Let _literal_ be ParseText(_text_, |StringNumericLiteral|). - 1. If _literal_ is a List of errors, return ~not-a-number~. + 1. Let _trimmedText_ be the longest prefix of _text_ that satisfies the syntax of a |StringNumericLiteral|, which might be _text_ itself. If there is no such prefix, return ~not-a-number~. + 1. NOTE: The previous step is a adapted from parseFloat. + 1. Let _literal_ be ParseText(_trimmedText_, |StringNumericLiteral|). + 1. If _literal_ is a List of errors, return ~not-a-number~. 1. Let _intlMV_ be the StringIntlMV of _literal_. 1. If _intlMV_ is a mathematical value, then 1. Let _rounded_ be RoundMVResult(abs(_intlMV_)). From a0de853fa0896b7b47372b8968c80100b3695d2b Mon Sep 17 00:00:00 2001 From: Jesse Alama Date: Thu, 13 Nov 2025 10:31:49 +0100 Subject: [PATCH 2/4] Don't use internal slots in argument position Use the `Get` and `Set` AOs. --- intl.emu | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/intl.emu b/intl.emu index 7db93d5..bc63664 100644 --- a/intl.emu +++ b/intl.emu @@ -29,12 +29,12 @@ 1. Let _O_ be the *this* value. 1. Perform ? RequireInternalSlot(_O_, [[Value]]). 1. Let _amountUnit_ be _O_.[[Unit]]. - 1. Let _optionsUnit_ be _options_.[[unit]]. + 1. Let _optionsUnit_ be ? Get(_options_, *"unit"*). 1. If _amountUnit_ is a String, then 1. If _optionsUnit_ is a String, then 1. If _amountUnit_ is not equal to _optionsUnit_, throw a *TypeError* exception. 1. Else, - 1. Set _options_.[[unit]] to _amountUnit_. + 1. Call ? Set(_options_., *"unit"*, _amountUnit_, *false*). 1. Let _numberFormat_ be ? Construct(%Intl.NumberFormat%, « _locales_, _options_ »). 1. Return FormatNumeric(_numberFormat_, _O_.[[Value]]). From a9254fd1928eb08b761e6951e535284f98f2ee5f Mon Sep 17 00:00:00 2001 From: Jesse Alama Date: Thu, 13 Nov 2025 10:54:52 +0100 Subject: [PATCH 3/4] Naively clone options object rather than modify --- intl.emu | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/intl.emu b/intl.emu index bc63664..5cef95b 100644 --- a/intl.emu +++ b/intl.emu @@ -29,12 +29,19 @@ 1. Let _O_ be the *this* value. 1. Perform ? RequireInternalSlot(_O_, [[Value]]). 1. Let _amountUnit_ be _O_.[[Unit]]. - 1. Let _optionsUnit_ be ? Get(_options_, *"unit"*). + 1. If _options_ is an Object, let _optionsUnit_ be ? Get(_options_, *"unit"*) else let _optionsUnit_ be *undefined*. 1. If _amountUnit_ is a String, then 1. If _optionsUnit_ is a String, then 1. If _amountUnit_ is not equal to _optionsUnit_, throw a *TypeError* exception. - 1. Else, - 1. Call ? Set(_options_., *"unit"*, _amountUnit_, *false*). + 1. Else if _options_ is an Object, then + 1. Let _propsAndValues_ be ? EnumerableOwnProperties(_options_, ~key+value~). + 1. Let _newOptions_ be OrdinaryObjectCreate(%Object.prototype%). + 1. For each element _propAndValue_ of _propsAndValues_, do + 1. Let _prop_ be _propAndValue_.[[0]]. + 1. Let _value_ be _propAndValue_.[[1]]. + 1. If _prop_ is *"unit"*, set _value_ to _amountUnit_. + 1. Call ? Set(_newOptions_, _prop_, _value_, *false*). + 1. Set _options_ to _newOptions_. 1. Let _numberFormat_ be ? Construct(%Intl.NumberFormat%, « _locales_, _options_ »). 1. Return FormatNumeric(_numberFormat_, _O_.[[Value]]). From 01853f05d805a1a1a4971a2750fa29573bae5ec6 Mon Sep 17 00:00:00 2001 From: Jesse Alama Date: Thu, 13 Nov 2025 11:03:29 +0100 Subject: [PATCH 4/4] fix minor typographic bugs --- spec.emu | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec.emu b/spec.emu index c186248..1ad4954 100644 --- a/spec.emu +++ b/spec.emu @@ -24,8 +24,8 @@ location: https://github.com/tc39/proposal-amount/

The Amount Object

Introduction

-

An Amount is an object that wraps mathematical value and a precision, together with a unit (e.g., mile, kilogram, EUR, JPY, USD-per-mile). One can intuitively understand an Amount as a number that, so to speak, knows its own precision and what it is measuring.

-

The notation for mathematical values used by Amount are decimal digit string, which are Strings that adhere to the DecimalLiteral production, excepting *"NaN"*, *"Infinity", and *"-Infinity"*.

+

An Amount is an object that wraps a mathematical value and a precision, together with a unit (e.g., mile, kilogram, EUR, JPY, USD-per-mile). One can intuitively understand an Amount as a number that, so to speak, knows its own precision and what it is measuring.

+

The notation for mathematical values used by Amount are decimal digit string, which are Strings that adhere to the DecimalLiteral production, excepting *"NaN"*, *"Infinity"*, and *"-Infinity"*.

Rounding a mathematical value is an important part of this spec. When we say rounding mode in this specification we simply refer to ECMA-402's definition.