diff --git a/intl.emu b/intl.emu index 4f3d209..4d03a0e 100644 --- a/intl.emu +++ b/intl.emu @@ -16,22 +16,126 @@

Amount.prototype.toLocaleString ( [ _locales_ [ , _options_ ] ] )

+

This definition supersedes the definition provided in es2025, .

-

- This definition supersedes the definition provided in es2025, . -

+

This function performs the following steps when called:

-

- This function performs the following steps when called: -

+ + 1. Let _O_ be the *this* value. + 1. Perform ? RequireInternalSlot(_O_, [[AmountValue]]). + 1. Let _v_ be _O_.[[AmountValue]]. + 1. If _v_ is a String, then + 1. Let _numValue_ be _v_. + 1. Else if _v_ is a BigInt, then + 1. Let _numValue_ be BigInt::toString(_v_, 10). + 1. Else, + 1. Assert: _v_ is a Number. + 1. Let _numValue_ be _v_. + 1. Let _unit_ be _O_.[[Unit]]. + 1. Let _mergedOptions_ be OrdinaryObjectCreate(*null*). + 1. If _options_ is not *undefined*, then + 1. Let _optionsObj_ be ? GetOptionsObject(_options_). + 1. Perform ? CopyDataProperties(_mergedOptions_, _optionsObj_, « »). + 1. If _unit_ is not *undefined*, then + 1. If ? HasProperty(_mergedOptions_, *"style"*) is *false*, then + 1. If IsWellFormedCurrencyCode(_unit_) is *true*, then + 1. Perform ! CreateDataPropertyOrThrow(_mergedOptions_, *"style"*, *"currency"*). + 1. If ? HasProperty(_mergedOptions_, *"currency"*) is *false*, then + 1. Perform ! CreateDataPropertyOrThrow(_mergedOptions_, *"currency"*, _unit_). + 1. Else, + 1. Perform ! CreateDataPropertyOrThrow(_mergedOptions_, *"style"*, *"unit"*). + 1. If ? HasProperty(_mergedOptions_, *"unit"*) is *false*, then + 1. Perform ! CreateDataPropertyOrThrow(_mergedOptions_, *"unit"*, _unit_). + 1. Let _numberFormat_ be ? Construct(%Intl.NumberFormat%, « _locales_, _mergedOptions_ »). + 1. Return FormatNumeric(_numberFormat_, _numValue_). + +
+ + +

Amount.prototype.convertTo ( _options_ )

+ +

This definition supersedes the definition provided in es2025, .

+ +

This function performs the following steps when called:

1. Let _O_ be the *this* value. - 1. Perform ? RequireInternalSlot(_O_, [[Decimal128Data]]). - 1. Let _numberFormat_ be ? Construct(%Intl.NumberFormat%, « _locales_, _options_ »). - 1. Return FormatNumeric(_numberFormat_, _O_.[[AmountData]]). + 1. Perform ? RequireInternalSlot(_O_, [[AmountValue]]). + 1. Let _sourceUnit_ be _O_.[[Unit]]. + 1. If _sourceUnit_ is *undefined*, throw a *TypeError* exception. + 1. Let _validatedOpts_ be ? GetAmountConvertToOptions(_options_). + 1. Let _targetUnit_ be _validatedOpts_.[[Unit]]. + 1. Let _roundingMode_ be _validatedOpts_.[[RoundingMode]]. + 1. Let _roundingPriority_ be _validatedOpts_.[[RoundingPriority]]. + 1. Let _minFractionDigits_ be _validatedOpts_.[[MiniumumFractionDigits]]. + 1. Let _maxFractionDigits_ be _validatedOpts_.[[MaximumFractionDigits]]. + 1. Let _minSignificantDigits_ be _validatedOpts_.[[MinimumSignificantDigits]]. + 1. Let _maxSignificantDigits_ be _validatedOpts_.[[MaximumSignificantDigits]]. + 1. Let _locale_ be _validatedOpts_.[[Locale]]. + 1. Let _usage_ be _validatedOpts_.[[Usage]]. + 1. If _targetUnit_ is *undefined* and _locale_ is *undefined* and _usage_ is *undefined*, throw a *TypeError* exception. + 1. Let _v_ be _O_.[[AmountValue]]. + 1. If _v_ is a Number, then + 1. Let _sourceValue_ be _v_. + 1. Else if _v_ is a BigInt, then + 1. Let _sourceValue_ be 𝔽(ℝ(_v_)). + 1. Else, + 1. Assert: _v_ is a String. + 1. Let _sourceValue_ be StringToNumber(_v_). + 1. If _targetUnit_ is not *undefined*, then + 1. If _locale_ is not *undefined* or _usage_ is not *undefined*, throw a *TypeError* exception. + 1. Else, + 1. Let _matcher_ be ? GetOption(_validatedOpts_, *"localeMatcher"*, ~string~, « *"lookup"*, *"best fit"* », *"best fit"*). + 1. Let _requestedLocales_ be ? CanonicalizeLocaleList(_locale_). + 1. If _usage_ is *undefined*, set _usage_ to *"default"*. + 1. Set _targetUnit_ to ? ResolveUnitPreference(_sourceUnit_, _sourceValue_, _requestedLocales_, _usage_, _matcher_). + 1. Let _convertedValue_ be ? ConvertUnitValue(_sourceValue_, _sourceUnit_, _targetUnit_). + 1. Let _result_ be OrdinaryObjectCreate(%Amount.prototype%, « [[AmountValue]], [[Unit]] »). + 1. TODO Let _intlObject_ be an Object suitable for use as the first argument of a call to FormatNumericToString that uses _minSignificantDigits_, _maxSignificantDigits_, _minFractionDigits_, _maxFractionDigits_, _roundingPriority_, and _roundingMode_. + 1. Let _formatted_ be FormatNumericToString(_intlObject_, _convertedValue_, 0). + 1. Set _result_.[[AmountValue]] to _formatted_.[[FormattedString]]. + 1. Set _result_.[[Unit]] to _targetUnit_. + 1. Return _result_.
+ + +

ResolveUnitPreference ( + _sourceUnit_: a String, + _sourceValue_: a Number, + _requestedLocales_: a Language Priority List, + _usage_: a String, + _localeMatcher_: a String, + ): either a normal completion containing a String or a throw completion +

+
+
description
+
It determines the preferred target unit for _sourceUnit_ in the locale best matching _requestedLocales_ and _usage_ context, based on CLDR unit preferences data.
+
+ + 1. Let _sourceConv_ be ? GetUnitConversionFactor(_sourceUnit_). + 1. Let _category_ be _sourceConv_.[[Category]]. + 1. Let _availableLocales_ be the Available Locales List for locales for which the <unitPreferences> element data of UTS #35 Part 6 Supplemental, Unit Preferences includes data. + 1. Let _localeData_ be a Record whose field names are the elements of _availableLocales_ and whose values are Records. + 1. Let _r_ be ResolveLocale(_availableLocales_, _requestedLocales_, the Record { [[localeMatcher]]: _localeMatcher_ }, « », _localeData_). + 1. Let _locale_ be _r_.[[Locale]]. + 1. Let _preferredUnit_ be the preferred unit for _category_, _locale_, _usage_, and _sourceValue_ as specified by the <unitPreferences> element data of UTS #35 Part 6 Supplemental, Unit Preferences. + 1. If _preferredUnit_ is *undefined*, throw a *RangeError* exception. + 1. Return _preferredUnit_. + +
+ + + +

Amendment to the Normative References of ECMA-402

+ +

The following entry is to be added to ECMA-402's list of referenced parts of Unicode Technical Standard #35.

+
+
@@ -138,41 +242,6 @@ - -

- ToIntlMathematicalValue ( - _value_: an ECMAScript language value, - ): either a normal completion containing an Intl mathematical value or a throw completion -

-
-
description
-
- It returns _value_ converted to an Intl mathematical value, which is a mathematical value together with ~positive-infinity~, ~negative-infinity~, ~not-a-number~, and ~negative-zero~. - This abstract operation is similar to , but a mathematical value can be returned instead of a Number or BigInt, so that exact decimal values can be represented. -
-
- - 1. If _value_ has the [[Value]] and [[FractionDigits]] internal slots, let _primValue_ be RenderAmountValueWithFractionDigits(_value_.[[Value]], _value_.[[FractionDigits]]) elseLet let𝔽, 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 _intlMV_ be the StringIntlMV of _literal_. - 1. If _intlMV_ is a mathematical value, then - 1. Let _rounded_ be RoundMVResult(abs(_intlMV_)). - 1. If _rounded_ is *+∞*𝔽 and _intlMV_ < 0, return ~negative-infinity~. - 1. If _rounded_ is *+∞*𝔽, return ~positive-infinity~. - 1. If _rounded_ is *+0*𝔽 and _intlMV_ < 0, return ~negative-zero~. - 1. If _rounded_ is *+0*𝔽, return 0. - 1. Return _intlMV_. - -

SetNumberFormatUnitOptions ( diff --git a/package.json b/package.json index 2a08108..b1e707d 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "scripts": { "start": "npm run build-loose -- --watch", "build": "npm run build-loose -- --strict", - "build-loose": "ecmarkup --load-biblio @tc39/ecma262-biblio --load-biblio @tc39/ecma402-biblio --verbose --lint-spec spec.emu index.html" + "build-loose": "ecmarkup --load-biblio @tc39/ecma262-biblio --load-biblio @tc39/ecma402-biblio --load-biblio ./proposal-intl-keep-trailing-zeros-biblio.json --verbose --lint-spec spec.emu index.html" }, "homepage": "https://github.com/tc39/template-for-proposals#readme", "repository": { diff --git a/proposal-intl-keep-trailing-zeros-biblio.json b/proposal-intl-keep-trailing-zeros-biblio.json new file mode 100644 index 0000000..285fc5e --- /dev/null +++ b/proposal-intl-keep-trailing-zeros-biblio.json @@ -0,0 +1 @@ +{"location":"https://tc39.es/proposal-intl-keep-trailing-zeros/","entries":[{"type":"op","aoid":"SetNumberFormatDigitOptions","refId":"sec-setnumberformatdigitoptions","kind":"abstract operation","signature":{"parameters":[{"name":"_intlObj_","type":{"kind":"opaque","type":"an Object"}},{"name":"_options_","type":{"kind":"opaque","type":"an Object"}},{"name":"_mnfdDefault_","type":{"kind":"opaque","type":"an integer"}},{"name":"_mxfdDefault_","type":{"kind":"opaque","type":"an integer"}},{"name":"_notation_","type":{"kind":"opaque","type":"a String"}}],"optionalParameters":[],"return":{"kind":"completion","completionType":"mixed","typeOfValueIfNormal":{"kind":"unused"}}},"effects":[]},{"type":"clause","id":"sec-setnumberformatdigitoptions","aoid":"SetNumberFormatDigitOptions","title":"SetNumberFormatDigitOptions ( intlObj, options, mnfdDefault, mxfdDefault, notation )","titleHTML":"SetNumberFormatDigitOptions ( intlObj, options, mnfdDefault, mxfdDefault, notation )","number":"16.1.2"},{"type":"clause","id":"sec-intl-numberformat-constructor","aoid":null,"title":"The Intl.NumberFormat Constructor","titleHTML":"The Intl.NumberFormat Constructor","number":"16.1"},{"type":"clause","id":"sec-properties-of-intl-numberformat-instances","aoid":null,"title":"Properties of Intl.NumberFormat Instances","titleHTML":"Properties of Intl.NumberFormat Instances","number":"16.4"},{"type":"op","aoid":"FormatNumericToString","refId":"sec-formatnumerictostring","kind":"abstract operation","signature":{"parameters":[{"name":"_intlObject_","type":{"kind":"opaque","type":"an Object"}},{"name":"_x_","type":{"kind":"union","types":[{"kind":"opaque","type":"a mathematical value"},{"kind":"opaque","type":"~negative-zero~"}]}},{"name":"_stringDigitCount_","type":{"kind":"opaque","type":"an integer"}}],"optionalParameters":[],"return":{"kind":"record","fields":{"[[RoundedNumber]]":{"kind":"union","types":[{"kind":"opaque","type":"a mathematical value"},{"kind":"opaque","type":"~negative-zero~"}]},"[[FormattedString]]":{"kind":"opaque","type":"a String"}}}},"effects":[]},{"type":"clause","id":"sec-formatnumerictostring","aoid":"FormatNumericToString","title":"FormatNumericToString ( intlObject, x, stringDigitCount )","titleHTML":"FormatNumericToString ( intlObject, x, stringDigitCount )","number":"16.5.3"},{"type":"op","aoid":"PartitionNumberPattern","refId":"sec-partitionnumberpattern","kind":"abstract operation","signature":{"parameters":[{"name":"_numberFormat_","type":{"kind":"opaque","type":"an object initialized as a NumberFormat"}},{"name":"_x_","type":{"kind":"union","types":[{"kind":"opaque","type":"a mathematical value"},{"kind":"opaque","type":" an Intl mathematical value"}]}}],"optionalParameters":[],"return":{"kind":"list","elements":{"kind":"record","fields":{"[[Type]]":{"kind":"opaque","type":"a String"},"[[Value]]":{"kind":"opaque","type":"a String"}}}}},"effects":[]},{"type":"clause","id":"sec-partitionnumberpattern","aoid":"PartitionNumberPattern","title":"PartitionNumberPattern ( numberFormat, x )","titleHTML":"PartitionNumberPattern ( numberFormat, x )","number":"16.5.4"},{"type":"op","aoid":"PartitionNotationSubPattern","refId":"sec-partitionnotationsubpattern","kind":"abstract operation","signature":{"parameters":[{"name":"_numberFormat_","type":{"kind":"opaque","type":"an Intl.NumberFormat"}},{"name":"_x_","type":{"kind":"union","types":[{"kind":"opaque","type":"an Intl mathematical valuea mathematical value"},{"kind":"opaque","type":"~negative-zero~"}]}},{"name":"_n_","type":{"kind":"opaque","type":"a String"}},{"name":"_exponent_","type":{"kind":"opaque","type":"an integer"}}],"optionalParameters":[],"return":{"kind":"list","elements":{"kind":"record","fields":{"[[Type]]":{"kind":"opaque","type":"a String"},"[[Value]]":{"kind":"opaque","type":"a String"}}}}},"effects":[]},{"type":"clause","id":"sec-partitionnotationsubpattern","aoid":"PartitionNotationSubPattern","title":"PartitionNotationSubPattern ( numberFormat, x, n, exponent )","titleHTML":"PartitionNotationSubPattern ( numberFormat, x, n, exponent )","number":"16.5.5"},{"type":"op","aoid":"FormatNumeric","refId":"sec-formatnumber","kind":"abstract operation","signature":{"parameters":[{"name":"_numberFormat_","type":{"kind":"opaque","type":"an Intl.NumberFormat"}},{"name":"_x_","type":{"kind":"union","types":[{"kind":"opaque","type":"a mathematical value"},{"kind":"opaque","type":" an Intl mathematical value"}]}}],"optionalParameters":[],"return":{"kind":"opaque","type":"a String"}},"effects":[]},{"type":"clause","id":"sec-formatnumber","aoid":"FormatNumeric","title":"FormatNumeric ( numberFormat, x )","titleHTML":"FormatNumeric ( numberFormat, x )","number":"16.5.6"},{"type":"op","aoid":"ToRawPrecisionFn","id":"eqn-ToRawPrecisionFn","signature":null,"effects":[]},{"type":"op","aoid":"ToRawPrecision","refId":"sec-torawprecision","kind":"abstract operation","signature":{"parameters":[{"name":"_x_","type":{"kind":"opaque","type":"a non-negative mathematical value"}},{"name":"_stringDigitCount_","type":{"kind":"opaque","type":"an integer"}},{"name":"_minPrecision_","type":{"kind":"opaque","type":"an integer in the inclusive interval from 1 to 21"}},{"name":"_maxPrecision_","type":{"kind":"opaque","type":"an integer in the inclusive interval from 1 to 21"}},{"name":"_unsignedRoundingMode_","type":{"kind":"union","types":[{"kind":"opaque","type":"a specification type from the Unsigned Rounding Mode column of "},{"kind":"opaque","type":"*undefined*"}]}}],"optionalParameters":[],"return":{"kind":"record","fields":{"[[FormattedString]]":{"kind":"opaque","type":"a String"},"[[RoundedNumber]]":{"kind":"opaque","type":"a mathematical value"},"[[IntegerDigitsCount]]":{"kind":"opaque","type":"an integer"},"[[RoundingMagnitude]]":{"kind":"opaque","type":"an integer"}}}},"effects":[]},{"type":"clause","id":"sec-torawprecision","aoid":"ToRawPrecision","title":"ToRawPrecision ( x, stringDigitCount, minPrecision, maxPrecision, unsignedRoundingMode )","titleHTML":"ToRawPrecision ( x, stringDigitCount, minPrecision, maxPrecision, unsignedRoundingMode )","number":"16.5.8"},{"type":"op","aoid":"ToRawFixedFn","id":"eqn-ToRawFixedFn","signature":null,"effects":[]},{"type":"op","aoid":"ToRawFixed","refId":"sec-torawfixed","kind":"abstract operation","signature":{"parameters":[{"name":"_x_","type":{"kind":"opaque","type":"a non-negative mathematical value"}},{"name":"_stringDigitCount_","type":{"kind":"opaque","type":"an integer"}},{"name":"_minFraction_","type":{"kind":"opaque","type":"an integer in the inclusive interval from 0 to 100"}},{"name":"_maxFraction_","type":{"kind":"opaque","type":"an integer in the inclusive interval from 0 to 100"}},{"name":"_roundingIncrement_","type":{"kind":"opaque","type":"an integer"}},{"name":"_unsignedRoundingMode_","type":{"kind":"union","types":[{"kind":"opaque","type":"a specification type from the Unsigned Rounding Mode column of "},{"kind":"opaque","type":"*undefined*"}]}}],"optionalParameters":[],"return":{"kind":"record","fields":{"[[FormattedString]]":{"kind":"opaque","type":"a String"},"[[RoundedNumber]]":{"kind":"opaque","type":"a mathematical value"},"[[IntegerDigitsCount]]":{"kind":"opaque","type":"an integer"},"[[RoundingMagnitude]]":{"kind":"opaque","type":"an integer"}}}},"effects":[]},{"type":"clause","id":"sec-torawfixed","aoid":"ToRawFixed","title":"ToRawFixed ( x, stringDigitCount, minFraction, maxFraction, roundingIncrement, unsignedRoundingMode )","titleHTML":"ToRawFixed ( x, stringDigitCount, minFraction, maxFraction, roundingIncrement, unsignedRoundingMode )","number":"16.5.9"},{"type":"op","aoid":"GetNumberFormatPattern","refId":"sec-getnumberformatpattern","kind":"abstract operation","signature":{"parameters":[{"name":"_numberFormat_","type":{"kind":"opaque","type":"an Intl.NumberFormat"}},{"name":"_x_","type":{"kind":"union","types":[{"kind":"opaque","type":"an Intl mathematical valueeither a mathematical value"},{"kind":"opaque","type":"~positive-infinity~"},{"kind":"opaque","type":"~negative-infinity~"},{"kind":"opaque","type":"~not-a-number~"},{"kind":"opaque","type":"~negative-zero~"}]}}],"optionalParameters":[],"return":{"kind":"opaque","type":"a String"}},"effects":[]},{"type":"clause","id":"sec-getnumberformatpattern","aoid":"GetNumberFormatPattern","title":"GetNumberFormatPattern ( numberFormat, x )","titleHTML":"GetNumberFormatPattern ( numberFormat, x )","number":"16.5.11"},{"type":"op","aoid":"ComputeExponent","refId":"sec-computeexponent","kind":"abstract operation","signature":{"parameters":[{"name":"_numberFormat_","type":{"kind":"opaque","type":"an Intl.NumberFormat"}},{"name":"_x_","type":{"kind":"opaque","type":"a mathematical value"}}],"optionalParameters":[],"return":{"kind":"opaque","type":"an integer"}},"effects":[]},{"type":"clause","id":"sec-computeexponent","aoid":"ComputeExponent","title":"ComputeExponent ( numberFormat, x )","titleHTML":"ComputeExponent ( numberFormat, x )","number":"16.5.13"},{"type":"op","aoid":"StringIntlMV","refId":"sec-runtime-semantics-stringintlmv","kind":"syntax-directed operation","signature":{"parameters":[],"optionalParameters":[],"return":null},"effects":[]},{"type":"clause","id":"sec-runtime-semantics-stringintlmv","aoid":"StringIntlMV","title":"Runtime Semantics: StringIntlMV","titleHTML":"Runtime Semantics: StringIntlMV","number":"16.5.15"},{"type":"op","aoid":"StringIntlMVFromParts","refId":"sec-stringintlmvfromparts","kind":"abstract operation","signature":{"parameters":[{"name":"_intPart_","type":{"kind":"union","types":[{"kind":"opaque","type":"a Parse Node"},{"kind":"opaque","type":"~empty~"}]}},{"name":"_fracPart_","type":{"kind":"union","types":[{"kind":"opaque","type":"a Parse Node"},{"kind":"opaque","type":"~empty~"}]}},{"name":"_e_","type":{"kind":"opaque","type":"a mathematical value"}}],"optionalParameters":[],"return":{"kind":"list","elements":null}},"effects":[]},{"type":"clause","id":"sec-stringintlmvfromparts","aoid":"StringIntlMVFromParts","title":"StringIntlMVFromParts ( intPart, fracPart, e )","titleHTML":"StringIntlMVFromParts ( intPart, fracPart, e )","number":"16.5.16"},{"type":"term","term":"Intl mathematical value","id":"intl-mathematical-value"},{"type":"op","aoid":"ToIntlMathematicalValue","refId":"sec-tointlmathematicalvalue","kind":"abstract operation","signature":{"parameters":[{"name":"_value_","type":{"kind":"opaque","type":"an ECMAScript language value"}}],"optionalParameters":[],"return":{"kind":"completion","completionType":"mixed","typeOfValueIfNormal":{"kind":"opaque","type":"an Intl mathematical value"}}},"effects":[]},{"type":"clause","id":"sec-tointlmathematicalvalue","aoid":"ToIntlMathematicalValue","title":"ToIntlMathematicalValue ( value )","titleHTML":"ToIntlMathematicalValue ( value )","number":"16.5.17"},{"type":"op","aoid":"PartitionNumberRangePattern","refId":"sec-partitionnumberrangepattern","kind":"abstract operation","signature":{"parameters":[{"name":"_numberFormat_","type":{"kind":"opaque","type":"an Intl.NumberFormat"}},{"name":"_x_","type":{"kind":"opaque","type":"an Intl mathematical value"}},{"name":"_y_","type":{"kind":"opaque","type":"an Intl mathematical value"}}],"optionalParameters":[],"return":{"kind":"completion","completionType":"mixed","typeOfValueIfNormal":{"kind":"list","elements":{"kind":"record","fields":{"[[Type]]":{"kind":"opaque","type":"a String"},"[[Value]]":{"kind":"opaque","type":"a String"},"[[Source]]":{"kind":"opaque","type":"a String"}}}}}},"effects":[]},{"type":"clause","id":"sec-partitionnumberrangepattern","aoid":"PartitionNumberRangePattern","title":"PartitionNumberRangePattern ( numberFormat, x, y )","titleHTML":"PartitionNumberRangePattern ( numberFormat, x, y )","number":"16.5.18"},{"type":"clause","id":"sec-numberformat-abstracts","aoid":null,"title":"Abstract Operations for NumberFormat Objects","titleHTML":"Abstract Operations for NumberFormat Objects","number":"16.5"},{"type":"clause","id":"numberformat-objects","aoid":null,"title":"NumberFormat Objects","titleHTML":"NumberFormat Objects","number":"16"},{"type":"clause","id":"sec-properties-of-intl-pluralrules-instances","aoid":null,"title":"Properties of Intl.PluralRules Instances","titleHTML":"Properties of Intl.PluralRules Instances","number":"17.4"},{"type":"op","aoid":"ResolvePlural","refId":"sec-resolveplural","kind":"abstract operation","signature":{"parameters":[{"name":"_pluralRules_","type":{"kind":"opaque","type":"an Intl.PluralRules"}},{"name":"_intlMV_","type":{"kind":"opaque","type":"an Intl mathematical value"}}],"optionalParameters":[],"return":{"kind":"record","fields":{"[[PluralCategory]]":{"kind":"union","types":[{"kind":"opaque","type":"*\"zero\"*"},{"kind":"opaque","type":"*\"one\"*"},{"kind":"opaque","type":"*\"two\"*"},{"kind":"opaque","type":"*\"few\"*"},{"kind":"opaque","type":"*\"many\"*"},{"kind":"opaque","type":"*\"other\"*"}]},"[[FormattedString]]":{"kind":"opaque","type":"a String"}}}},"effects":[]},{"type":"clause","id":"sec-resolveplural","aoid":"ResolvePlural","title":"ResolvePlural ( pluralRules, n, intlMV )","titleHTML":"ResolvePlural ( pluralRules, n, intlMV )","number":"17.5.2"},{"type":"op","aoid":"ResolvePluralRange","refId":"sec-resolvepluralrange","kind":"abstract operation","signature":{"parameters":[{"name":"_pluralRules_","type":{"kind":"opaque","type":"an Intl.PluralRules"}},{"name":"_x_","type":{"kind":"opaque","type":"an Intl mathematical value"}},{"name":"_y_","type":{"kind":"opaque","type":"an Intl mathematical value"}}],"optionalParameters":[],"return":{"kind":"completion","completionType":"mixed","typeOfValueIfNormal":{"kind":"union","types":[{"kind":"opaque","type":"*\"zero\"*"},{"kind":"opaque","type":"*\"one\"*"},{"kind":"opaque","type":"*\"two\"*"},{"kind":"opaque","type":"*\"few\"*"},{"kind":"opaque","type":"*\"many\"*"},{"kind":"opaque","type":"*\"other\"*"}]}}},"effects":[]},{"type":"clause","id":"sec-resolvepluralrange","aoid":"ResolvePluralRange","title":"ResolvePluralRange ( pluralRules, x, y )","titleHTML":"ResolvePluralRange ( pluralRules, x, y )","number":"17.5.4"},{"type":"clause","id":"sec-intl-pluralrules-abstracts","aoid":null,"title":"Abstract Operations for PluralRules Objects","titleHTML":"Abstract Operations for PluralRules Objects","number":"17.5"},{"type":"clause","id":"pluralrules-objects","aoid":null,"title":"PluralRules Objects","titleHTML":"PluralRules Objects","number":"17"},{"type":"clause","id":"sec-copyright-and-software-license","aoid":null,"title":"Copyright & Software License","titleHTML":"Copyright & Software License","number":"A"}]} \ No newline at end of file diff --git a/spec.emu b/spec.emu index c186248..a1d4ae8 100644 --- a/spec.emu +++ b/spec.emu @@ -15,26 +15,30 @@ location: https://github.com/tc39/proposal-amount/

Introduction

This specification consists of two parts:

+ +

+ The changes proposed here are stacked on top of the Keep Trailing Zeros ECMA-402 proposal, + and include calls to ECMA-402 Abstract Operations from ECMA​-262 algorithms. + Where necessary, we intend to promote those semantics to ECMA​-262. +

+

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 numeric value—as a Number, BigInt, or String—together with an optional unit (e.g., mile, kilogram, EUR, JPY, USD-per-mile). One can intuitively understand an Amount as a value that, so to speak, knows what it is measuring.

+

When precision options (such as fractionDigits or significantDigits) are applied, or when unit conversion is performed, the numeric value is stored as a decimal digit string, which is a String in |StrDecimalLiteral| form or *"NaN"*. Otherwise, the original JavaScript value type (Number, BigInt, or String) is retained.

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.

Abstract Operations

- -

Operations for Reading Options

- @@ -69,316 +73,113 @@ location: https://github.com/tc39/proposal-amount/ 1. Return _value_.
-
- - - -

Runtime Semantics: StringIntlMV

-
-
- - -

The - conversion of a |StringNumericLiteral| to a Number value is similar overall to the determination of the NumericValue of a |NumericLiteral| (see ), but some of the details are different.

-
- -

- The conversion of a |StringNumericLiteral| to a mathematical value and a precision is similar overall to the determination of the NumericValue of a |NumericLiteral| (see ), but some of the details are different. - The result of StringIntlMV is a List value with two elements, a mathematical value and the count of decimal digits in the source text. -

-
-
- StringNumericLiteral ::: StrWhiteSpace? - - 1. Return 0« 0, 0 ». - - StringNumericLiteral ::: StrWhiteSpace? StrNumericLiteral StrWhiteSpace? - - 1. Return StringIntlMV of |StrNumericLiteral|. - - StrNumericLiteral ::: NonDecimalIntegerLiteral - - 1. Return MV of |NonDecimalIntegerLiteral|. - 1. Let _i_ be MV of |NonDecimalIntegerLiteral|. - 1. Return « _i_, 0 ». - - StrDecimalLiteral ::: `-` StrUnsignedDecimalLiteral - - 1. Let _a__x_ be StringIntlMV of |StrUnsignedDecimalLiteral|. - 1. Let _a_ be the first element of _x_. - 1. Let _n_ be the second element of _x_. - 1. If _a_ is 0, return ~negative-zero~« ~negative-zero~, _n_ ». - 1. If _a_ is ~positive-infinity~, return ~negative-infinity~« ~negative-infinity~, 0 ». - 1. Return -_a_« -_a_, _n_ ». - - StrUnsignedDecimalLiteral ::: `Infinity` - - 1. Return ~positive-infinity~« ~positive-infinity~, 0 ». - - StrUnsignedDecimalLiteral ::: DecimalDigits `.` DecimalDigits? ExponentPart? - - 1. Let _a_ be MV of the first |DecimalDigits|. - 1. Let _m_ be the number of code points in the first |DecimalDigits|. - 1. If the second |DecimalDigits| is present, then - 1. Let _b_ be MV of the second |DecimalDigits|. - 1. Let _n_ be the number of code points in the second |DecimalDigits|. - 1. Else, - 1. Let _b_ be 0. - 1. Let _n_ be 0. - 1. If |ExponentPart| is present, let _e_ be MV of |ExponentPart|. Otherwise, let _e_ be 0. - 1. Return « (_a_ + (_b_ × 10-_n_)) × 10_e_, _m_ + _n_ ». - - StrUnsignedDecimalLiteral ::: `.` DecimalDigits ExponentPart? - - 1. Let _b_ be MV of |DecimalDigits|. - 1. If |ExponentPart| is present, let _e_ be MV of |ExponentPart|. Otherwise, let _e_ be 0. - 1. Let _n_ be the number of code points in |DecimalDigits|. - 1. Return « _b_ × 10_e_ - _n_, _n_ ». - - StrUnsignedDecimalLiteral ::: DecimalDigits ExponentPart? - - 1. Let _a_ be MV of |DecimalDigits|. - 1. Let _m_ be the number of code points in |DecimalDigits|. - 1. If |ExponentPart| is present, let _e_ be MV of |ExponentPart|. Otherwise, let _e_ be 0. - 1. Return « _a_ × 10_e_, _m_ ». - -
- - -

Runtime Semantics: CountFractionDigits

-
-
- -

It computes the power of 10 of the least significant precise digit of a |StringNumericLiteral|.

-
- StringNumericLiteral ::: StrWhiteSpace? - - 1. Return 0. - - StringNumericLiteral ::: StrWhiteSpace? StrNumericLiteral StrWhiteSpace? - - 1. Return CountFractionDigits of |StrNumericLiteral|. - - StrNumericLiteral ::: NonDecimalIntegerLiteral - - 1. Return 0. - - StrUnsignedDecimalLiteral ::: `Infinity` - - 1. Return 0. - - StrUnsignedDecimalLiteral ::: DecimalDigits `.` DecimalDigits? ExponentPart? - - 1. If |ExponentPart| is present, let _e_ be the MV of |ExponentPart|, else let _e_ be 0. - 1. If the second |DecimalDigits| is present, let _m_ be the number of code points in the second |DecimalDigits|, else let _m_ be 0. - 1. Return _m_ - _e_. - - StrUnsignedDecimalLiteral ::: `.` DecimalDigits ExponentPart? - - 1. Let _m_ be the number of code points in |DecimalDigits|. - 1. If |ExponentPart| is present, let _e_ be MV of |ExponentPart|. Otherwise, let _e_ be 0. - 1. Return _m_ - _e_. - - StrUnsignedDecimalLiteral ::: DecimalDigits ExponentPart? - - 1. If |ExponentPart| is present, let _e_ be MV of |ExponentPart|. Otherwise, let _e_ be 0. - 1. Return -_e_. - -
- - -

Abstract Operations

- - -

ApplyRoundingModeToPositive( - _m_: a positive mathematical value, - _roundingMode_: a rounding mode - ): an integer + +

GetAmountOptions ( + _opts_: an Object + ): either a normal completion containing a Record with fields [[FractionDigits]] (a non-negative integer or *undefined*), [[RoundingMode]] (a rounding mode), [[SignificantDigits]] (a positive integer or *undefined*), and [[Unit]] (a String or *undefined*) or a throw completion

description
-
It computes the closest integer approximation to a given positive mathematical value, rounded according to the given rounding mode.
+
It validates the given _options_ (an ECMAScript object) for creating an Amount and returns a Record with slots set to appropriate marthematical values (or *undefined*).
- 1. Let _mLow_ be floor(_m_). - 1. Let _fraction_ be _m_ – _mLow_. - 1. If _fraction_ = 0, return _mLow_. - 1. Let _mHigh_ be _mLow_ + 1. - 1. If _roundingMode_ is *"floor"* or *"trunc"*, return _mLow_. - 1. If _roundingMode_ is *"ceil" or *"expand"*, return _mHigh_. - 1. If _fraction_ < 0.5, return _mLow_. - 1. If _fraction_ > 0.5, return _mHigh_. - 1. If _roundingMode_ is *"halfTrunc"* or *"halfFloor"*, return _mLow_. - 1. If _roundingMode_ is *"halfExpand"* or *"halfCeil"*, return _mHigh_. - 1. If _mLow_ is even, return _mLow_. - 1. Return _mHigh_. + 1. Let _opts_ be ? GetOptionsObject(_opts_). + 1. Let _fractionDigits_ be ? GetOption(_opts_, *"fractionDigits"*, ~number~, ~empty~, *undefined*). + 1. Let _roundingMode_ be ? GetOption(_opts_, *"roundingMode"*, ~string~, « *"ceil"*, *"floor"*, *"expand"*, *"trunc"*, *"halfCeil"*, *"halfFloor"*, *"halfExpand"*, *"halfTrunc"*, *"halfEven"* », *"halfEven"*). + 1. Let _significantDigits_ be ? GetOption(_opts_, *"significantDigits"*, ~number~, ~empty~, *undefined*). + 1. Let _unit_ be ? GetOption(_opts_, *"unit"*, ~string~, ~empty~, *undefined*). + 1. If _fractionDigits_ is not *undefined*, then + 1. If _significantDigits_ is not *undefined*, throw a *RangeError* exception. + 1. If _fractionDigits_ is not an integral Number, throw a *RangeError* exception. + 1. Else if _significantDigits_ is not *undefined*, then + 1. If _significantDigits_ is not an integral Number, throw a *RangeError* exception. + 1. If _significantDigits_ < *1*𝔽, throw a *RangeError* exception. + 1. If _unit_ is the empty String, throw a *RangeError* exception. + 1. Return the Record { [[FractionDigits]]: _fractionDigits_, [[RoundingMode]]: _roundingMode_, [[SignificantDigits]]: _significantDigits_, [[Unit]]: _unit_ }.
- -

ReverseRoundingMode ( - _mode_: a rounding mode - ): a rounding mode -

-
-
description
-
It computes the rounding mode that would be used if we were to rounding a negative mathematical value with the given rounding mode.
-
- - 1. If _mode_ is *"floor"*, return *"ceil"*. - 1. If _mode_ is *"ceil"*, return *"floor"*. - 1. If _mode_ is *"halfCeil"*, return *"halfFloor"*. - 1. If _mode_ is *"halfFloor"*, return *"halfCeil"*. - 1. Otherwise, return _mode_. - -
- - -

RoundAmountValueToFractionDigits( - _v_: a mathematical value, - _n_: an integer, - optional _roundingMode_: a rounding mode - ): a mathematical value + +

GetAmountConvertToOptions ( + _opts_: an Object + ): either a normal completion containing a Record with fields [[MinFractionDigits]] (a non-negative integer or *undefined*), [[MaxFractionDigits]] (a non-negative integer or *undefined*), [[RoundingMode]] (a rounding mode), [[RoundingPriority]] (a String), [[MinSignificantDigits]] (a positive integer or *undefined*), [[MaxSignificantDigits]] (a positive integer or *undefined*), [[Locale]] (a String or *undefined*), [[Usage]] (a String or *undefined*), and [[Unit]] (a String or *undefined*) or a throw completion

description
-
It computes the closest approximation to a given mathematical value that has at most the given number of fractional digits, rounding (if necessary) according to the given rounding mode.
+
It validates the given _options_ (an ECMAScript object) for converting an Amount to another Amount and returns a Record with slots set to appropriate marthematical values (or *undefined*).
- 1. If _v_ = 0, return 0. - 1. If _roundingMode_ is *undefined*, set _roundingMode_ to *"halfEven"*. - 1. If v < 0, then - 1. Let _reverseRoundingMode_ be _roundingMode_. - 1. If _roundingMode_ is *"floor"*, set _reverseRoundingMode_ to *"ceil"*. - 1. If _roundingMode_ is *"ceil"*, set _reverseRoundingMode_ to *"floor"*. - 1. If _roundingMode_ is *"halfCeil"*, set _reverseRoundingMode_ to *"halfFloor"*. - 1. If _roundingMode_ is *"halfFloor"*, set _reverseRoundingMode_ to *"halfCeil"*. - 1. Let _d_ be RoundAmountValueToFractionDigits(–_v_, _n_, _reverseRoundingMode_). - 1. Return –_d_. - 1. Let _m_ be _v_ × 10_n_. - 1. Let _rounded_ be ApplyRoundingModeToPositive(_m_, _roundingMode_). - 1. Return _rounded_ × 10-_n_. + 1. Let _opts_ be ? GetOptionsObject(_opts_). + 1. Let _minFractionDigits_ be ? GetOption(_opts_, *"minimumfractionDigits"*, ~number~, ~empty~, *undefined*). + 1. Let _maxFractionDigits_ be ? GetOption(_opts_, *"maximumfractionDigits"*, ~number~, ~empty~, *undefined*). + 1. Let _roundingMode_ be ? GetOption(_opts_, *"roundingMode"*, ~string~, « *"ceil"*, *"floor"*, *"expand"*, *"trunc"*, *"halfCeil"*, *"halfFloor"*, *"halfExpand"*, *"halfTrunc"*, *"halfEven"* », *"halfEven"*). + 1. Let _roundingPriority_ be ? GetOption(_opts_, *"roundingPriority"*, ~string~, ~empty~, *undefined*). + 1. Let _minSignificantDigits_ be ? GetOption(_opts_, *"minimumSignificantDigits"*, ~number~, ~empty~, *undefined*). + 1. Let _maxSignificantDigits_ be ? GetOption(_opts_, *"maximumSignificantDigits"*, ~number~, ~empty~, *undefined*). + 1. Let _significantDigits_ be ? GetOption(_opts_, *"maximumSignificantDigits"*, ~number~, ~empty~, *undefined*). + 1. Let _unit_ be ? GetOption(_opts_, *"unit"*, ~string~, ~empty~, *undefined*). + 1. If _minFractionDigits_ is not *undefined* and not an integral Number, throw a *RangeError* exception. + 1. If _maxFractionDigits_ is not *undefined* and not an integral Number, throw a *RangeError* exception. + 1. If _minSignificantDigits_ is not *undefined* and not an integral Number, throw a *RangeError* exception. + 1. If _maxSignificantDigits_ is not *undefined* and not an integral Number, throw a *RangeError* exception. + 1. If _unit_ is the empty String, throw a *RangeError* exception. + 1. Return the Record { [[MinimumFractionDigits]]: _minFractionDigits_, [[MaximumFractionDigits]]: _maxFractionDigits_, [[MinimumSignificantDigits]]: _minSignificantDigits_, [[MaximumSignificantDigits]]: _maxSignificantDigits_, [[RoundingMode]]: _roundingMode_, [[RoundingPriority]]: _roundingPriority_, [[SignificantDigits]]: _significantDigits_, [[Unit]]: _unit_ }. + +

+ This abstract operation will need to be overridden in the 402 part because it will read additional Intl-specific properties beyond these. +

+
- -

RenderAmountValueWithFractionDigits ( - _v_: an Intl mathematical value, - _numDigits_: an integer, - optional _roundingMode_: a rounding mode - ): a String + +

GetUnitConversionFactor ( + _unit_: a String + ): either a normal completion containing a Record with fields [[Category]] (a String), [[Factor]] (a Number), and [[Offset]] (a Number) or a throw completion

description
-
It renders the given Intl mathematical value with a given number of fractional digits, rounding, if necessary, using the given rounding mode, which, if missing, is *"halfEven"*.
+
It returns the conversion data for converting _unit_ to its base unit within its unit category.
- 1. If _v_ is ~not-a-number~, return *"NaN"*. - 1. If _v_ is ~negative-infinity~, return *"-Infinity"*. - 1. If _v_ is ~positive-infinity~, return *"Infinity"*. - 1. If _v_ is ~minus-zero~, then - 1. If _numDigits_ < 0, then - 1. Let _exp_ be the unique string representation of -_numDigits_ in base 10 without duplicate leading zeros. - 1. Return the string-concatenation of *"0"*, *"e"*, and _exp_. - 1. Otherwise: - 1. Let _trailingZeroes_ be *"0"* repeated _numDigits_ times. - 1. Let _z_ be *"-0"*. - 1. If _numDigits_ = 0, return _z_. - 1. Otherwise, return the string-concatenation of _z_, *"."* and _trailingZeroes_. - 1. If _roundingMode_ is *undefined*, set _roundingMode_ to *"halfEven"*. - 1. If _v_ < 0, let _prefix_ be *"-"*, else let _prefix_ be "". - 1. If _v_ < 0, then - 1. Set _v_ to -_v_. - 1. Set _roundingMode_ to ReverseRoundingMode(_roundingMode_). - 1. Let _rounded_ be ApplyRoundingModeToPositive(_v_ × 10_numDigits_, _roundingMode_). - 1. Let _e_ be the smallest non-negative integer such that _rounded_ × 10-_numDigits_ is an integer. - 1. Let _s_ be the unique decimal string representation of _rounded_ without duplicate leading zeroes. - 1. If _numDigits_ > _e_, then - 1. If _v_ is an integer, return the string-concatenation of _prefix, _s_, *"."*, and *"0"* repeated _numDigits_ times. - 1. Otherwise, return the string-concatenation of _prefix_, _s_ and *"0"* repeated _numDigits_ - _e_ times. - 1. If 0 < _numDigits_, then - 1. Return the string-concatenation of _prefix, _s_ and *"0"* repeated _e_ - _numDigits_ times. - 1. Otherwise: - 1. Assert: _rounded_ is an integer. - 1. Let _firstDigit_ be the substring of _s_ from 0 to 1. - 1. Let _p_ be the unique integer such that 1 ≤ _rounded_ × 10_p_ < 10. - 1. Let _n_ be _p_ + _numDigits_. - 1. Assert: _n_ ≥ 0. - 1. Let _exp_ be the unique string representation of _n_ in base-10 without duplicate leading zeros. - 1. If _n_ = 0, then - 1. Return the string-concatenation of _s_, *"e"*, and _exp_. - 1. Otherwise: - 1. Let _remainingDigits_ be the substring of _s_ from 1 to _n_. - 1. Return the string-concatenation of _firstDigit_, *"."*, _remainingDigits_, *"e"*, and _exp_. + 1. If _unit_ does not have a corresponding <convertUnit> element in UTS #35 Part 6 Supplemental, Unit Conversion, or if that element specifies a special conversion, throw a *RangeError* exception. + 1. Let _category_ be the unit category of _unit_ as specified by the CLDR unit conversion data. + 1. Let _factor_ be the Number value closest to the rational conversion factor for _unit_ as specified by the CLDR unit conversion data. + 1. If the CLDR unit conversion data specifies a conversion offset for _unit_, let _offset_ be the Number value closest to that rational offset; otherwise, let _offset_ be *+0*𝔽. + 1. Return the Record { [[Category]]: _category_, [[Factor]]: _factor_, [[Offset]]: _offset_ }. + +

The formula for converting a value in _unit_ to its base unit is: baseValue = value × [[Factor]] + [[Offset]].

+

CLDR expresses conversion factors as rational numbers (e.g., 0.3048/12 for inch-to-meter). These rational values are converted to Numbers before use, so conversion arithmetic is subject to the precision of IEEE 754 binary64. For example, converting 1.75 feet to inches yields 1.75 × 0.3048 / (0.3048 / 12) = 20.999999999999996, not exactly 21.

+

CLDR also defines nonlinear conversions via the special attribute (e.g., the Beaufort scale). These cannot be expressed as a linear factor and offset, so they are excluded from this operation.

+
- -

FractionToSignificantDigits ( - _value_: an Intl mathematical value, - _fractionDigits_: an integer - ): a non-negative integer -

-
- - 1. If _value_ is one of ~not-a-number~, ~positive-infinity~, or ~negative-infinity~, then - 1. Return 0. - 1. If _value_ is one of 0 or ~negative-zero~, then - 1. If _fractionDigits_ < 0, return 1. - 1. Let _integerDigits_ be 1. - 1. Else, - 1. Let _integerDigits_ be the smallest integer such that 10_integerDigits_ > abs(_value_). - 1. Assert: _integerDigits_ + _fractionDigits_ > 0. - 1. Return _integerDigits_ + _fractionDigits_. - -
- - -

SignificantToFractionDigits ( - _value_: an Intl mathematical value, - _significantDigits_: a positive integer - ): an integer -

-
- - 1. If _value_ is one of ~not-a-number~, ~positive-infinity~, or ~negative-infinity~, then - 1. Return 0. - 1. If _value_ is one of 0 or ~negative-zero~, then - 1. Let _integerDigits_ be 1. - 1. Else, - 1. Let _integerDigits_ be the smallest integer such that 10_integerDigits_ > abs(_value_). - 1. Assert: _significantDigits_ > 0. - 1. Return _significantDigits_ - _integerDigits_. - -
- - -

GetAmountOptions ( - _opts_: an Object - ): either a normal completion containing a Record with fields [[FractionDigits]] (a non-negative integer or *undefined*), [[RoundingMode]] (a rounding mode), [[SignificantDigits]] (a positive integer or *undefined*), and [[Unit]] (a String or *undefined*) or a throw completion + +

ConvertUnitValue ( + _value_: a Number, + _sourceUnit_: a String, + _targetUnit_: a String + ): either a normal completion containing a Number or a throw completion

description
-
It validates the given _options_ (an ECMAScript object) for creating an Amount and returns a Record with slots set to appropriate marthematical values (or *undefined*).
+
It converts _value_ from _sourceUnit_ to _targetUnit_ using Number arithmetic.
- 1. Let _opts_ be ? GetOptionsObject(_opts_). - 1. Let _fractionDigits_ be ? GetOption(_opts_, *"fractionDigits"*, ~number~, ~empty~, *undefined*). - 1. Let _roundingMode_ be ? GetOption(_opts_, *"roundingMode"*, ~string~, « *"ceil"*, *"floor"*, *"expand"*, *"trunc"*, *"halfCeil"*, *"halfFloor"*, *"halfExpand"*, *"halfTrunc"*, *"halfEven"* », *"halfEven"*). - 1. Let _significantDigits_ be ? GetOption(_opts_, *"significantDigits"*, ~number~, ~empty~, *undefined*). - 1. Let _unit_ be ? GetOption(_opts_, *"unit"*, ~string~, ~empty~, *undefined*). - 1. If _fractionDigits_ is not *undefined*, then - 1. If _significantDigits_ is not *undefined*, throw a *RangeError* exception. - 1. If _fractionDigits_ is not an integral number, throw a *RangeError* exception. - 1. Else if _significantDigits_ is not *undefined*, then - 1. If _significantDigits_ is not an integral number, throw a *RangeError* exception. - 1. If ℝ(_significantDigits_) < 1, throw a *RangeError* exception. - 1. If _unit_ is the empty String, throw a *RangeError* exception. - 1. Return the Record { [[FractionDigits]]: _fractionDigits_, [[RoundingMode]]: _roundingMode_, [[SignificantDigits]]: _significantDigits, [[Units]]: _unit_ }. + 1. Let _sourceConv_ be ? GetUnitConversionFactor(_sourceUnit_). + 1. Let _targetConv_ be ? GetUnitConversionFactor(_targetUnit_). + 1. If SameValue(_sourceConv_.[[Category]], _targetConv_.[[Category]]) is *false*, throw a *RangeError* exception. + 1. Let _sourceFactor_ be _sourceConv_.[[Factor]]. + 1. Let _sourceOffset_ be _sourceConv_.[[Offset]]. + 1. Let _targetFactor_ be _targetConv_.[[Factor]]. + 1. Let _targetOffset_ be _targetConv_.[[Offset]]. + 1. Let _baseValue_ be _value_ × _sourceFactor_ + _sourceOffset_. + 1. Let _result_ be (_baseValue_ - _targetOffset_) / _targetFactor_. + 1. Return _result_.
- @@ -394,40 +195,36 @@ location: https://github.com/tc39/proposal-amount/

Amount ( _x_ [ , _opts_ ] )

1. If NewTarget is *undefined*, throw a *TypeError* exception. - 1. Let _toParse_ be *undefined*. - 1. If _x_ is a BigInt, set _toParse_ to BigInt::toString(_x_, 10). - 1. Else if _x_ is a Number, set _toParse_ to Number::toString(_x_, 10). - 1. Otherwise, if _x_ is a String, set _toParse_ to _x_. - 1. If _toParse_ is not a String, throw a *TypeError* exception. - 1. Let _parsed_ be ParseText(_toParse_, |StringNumericLiteral|). - 1. If _parsed_ is a List of errors, then - 1. Let _amountValue_ be ~not-a-number~. - 1. Else, - 1. Let _intlMV_ be the StringIntlMV of _parsed_. - 1. Let _amountValue_ be _intlMV_[0]. + 1. If _x_ is not a Number, not a BigInt, and not a String, throw a *TypeError* exception. + 1. If _x_ is a String, then + 1. Let _text_ be StringToCodePoints(_x_). + 1. Let _parsed_ be ParseText(_text_, |StringNumericLiteral|). + 1. If _parsed_ is a List of errors, throw a *RangeError* exception. 1. Let _validatedOpts_ be ? GetAmountOptions(_opts_). 1. Let _roundingMode_ be _validatedOpts_.[[RoundingMode]]. 1. Let _fractionDigits_ be _validatedOpts_.[[FractionDigits]]. 1. Let _significantDigits_ be _validatedOpts_.[[SignificantDigits]]. 1. Let _unit_ be _validatedOpts_.[[Unit]]. - 1. Let _O_ be OrdinaryObjectCreate(%Amount.prototype%, « [[FractionDigits]], [[Unit]], [[Value]] »). - 1. If _fractionDigits_ is *undefined*, then - 1. If _significantDigits_ is not *undefined*, then - 1. Set _fractionDigits_ to SignificantToFractionDigits(_amountValue_, _significantDigits_). - 1. Else if _amountValue_ is a mathematical value or ~negative-zero~, then - 1. Set _fractionDigits_ to the CountFractionDigits of _toParse_. - 1. Else, - 1. Set _fractionDigits_ to 0. - 1. Set _O_.[[FractionDigits]] to _fractionDigits_. - 1. If _amountValue_ is a mathematical value, then - 1. Set _O_.[[Value]] to RoundAmountValueToFractionDigits(_amountValue_, _fractionDigits_, _roundingMode_). + 1. If _x_ is a Number or _x_ is a BigInt, then + 1. Let _value_ be _x_. 1. Else, - 1. Set _O_.[[Value]] to _amountValue_. - 1. If _unit_ is not *undefined* and _amountValue_ is not ~not-a-number~, set _O_.[[Unit]] to _unit_. + 1. Assert: _x_ is a String. + 1. TODO Let _intlObject_ be an Object suitable as a first argument FormatNumericToString, using _fractionDigits_, _significantDigits_, and _roundingMode_. + 1. Let _intlMV_ be ! ToIntlMathematicalValue(_x_). + 1. Let _formatted_ be FormatNumericToString(_intlObject_, _intlMV_.[[Value]], _intlMV_.[[StringDigitCount]]). + 1. Let _value_ be _formatted_.[[FormattedString]]. + 1. Let _O_ be OrdinaryObjectCreate(%Amount.prototype%, « [[AmountValue]], [[Unit]] »). + 1. Set _O_.[[AmountValue]] to _value_. + 1. Set _O_.[[Unit]] to _unit_. 1. Return _O_. -

Given a Number argument, the constructor converts it to a String using the toString method (with no arguments). In some cases, this may not be desired; consider passing in a String form of a Number using the toFixed or toPrecision methods.

+

When no precision options are given, Number and BigInt arguments are stored directly in [[AmountValue]], preserving the original type. String arguments are normalized to StrDecimalLiteral form. When precision options are specified, [[AmountValue]] always holds a String.

+
+ +

+ We intend to move 402's FormatNumericToString, and its dependent AOs, to 262, possibly renamed. +

@@ -436,112 +233,114 @@ location: https://github.com/tc39/proposal-amount/

Properties of the Amount Prototype

- -

get Decimal.prototype.fractionDigits

-

This accessor property, whose set accessor function is *undefined*, stores a Number value indicating how many fraction digits an Amount contains. Its get accessor function performs the following steps when called:

+ +

get Amount.prototype.value

+

This accessor property, whose set accessor function is *undefined*, returns the numeric value of the Amount. Its get accessor function performs the following steps when called:

1. Let _O_ be the *this* value. - 1. Perform ? RequireInternalSlot(_O_, [[FractionDigits]]). - 1. Let _fractionDigits_ be _O_.[[FractionDigits]]. - 1. Return 𝔽(_fractionDigits_). - -
- - -

get Decimal.prototype.significantDigits

-

This accessor property, whose set accessor function is *undefined*, stores a Number value indicating how many significant digits an Amount contains. Its get accessor function performs the following steps when called:

- - 1. Let _O_ be the *this* value. - 1. Perform ? RequireInternalSlot(_O_, [[SignificantDigits]]). - 1. Let _significantDigits_ be _O_.[[SignificantDigits]]. - 1. Return 𝔽(_significantDigits_). + 1. Perform ? RequireInternalSlot(_O_, [[AmountValue]]). + 1. Return _O_.[[AmountValue]]. + +

The value may be a Number, BigInt, or String. It is a String when precision options were applied during construction or when the Amount is the result of unit conversion.

+
-

get Decimal.prototype.unit

-

This accessor property, whose set accessor function is *undefined*, stores a String value (or *undefined*) indicating the unit that this Amount has. Its get accessor function performs the following steps when called:

+

get Amount.prototype.unit

+

This accessor property, whose set accessor function is *undefined*, returns a String value (or *undefined*) indicating the unit that this Amount has. Its get accessor function performs the following steps when called:

1. Let _O_ be the *this* value. - 1. Perform ? RequireInternalSlot(_O_, [[Unit]]). + 1. Perform ? RequireInternalSlot(_O_, [[AmountValue]]). 1. Return _O_.[[Unit]].
-

Amount.prototype.toString ( [ _options_ ] )

-

This method returns a String value that renders the underlying mathematical value according to its precision, as well as a unit indicator, if present.

+

Amount.prototype.toString ( )

+

This method returns a String representation of the Amount, including a unit indicator in bracket notation.

It performs the following steps when called:

1. Let _O_ be the *this* value. - 1. Perform ? RequireInternalSlot(_O_, [[Value]]). - 1. Perform ? RequireInternalSlot(_O_, [[FractionDigits]]). - 1. Let _processedOptions_ be ? GetOptionsObject(_options_). - 1. Let _displayUnit_ be ? GetOption(_processedOptions_, *"displayUnit"*, ~string~, « *"always"*, *"auto"*, *"never"* », *"auto"*). + 1. Perform ? RequireInternalSlot(_O_, [[AmountValue]]). + 1. Let _v_ be _O_.[[AmountValue]]. 1. Let _u_ be _O_.[[Unit]]. - 1. Let _v_ be _O_.[[Value]]. - 1. Let _fractionDigits_ be _O_.[[FractionDigits]]. - 1. Let _s_ be RenderAmountValueWithFractionDigits(_v_, _fractionDigits_). - 1. If _displayUnit_ is *"never"*, return _s_. - 1. If _u_ is *undefined*, then - 1. If _displayUnit_ is *"always"*, return the string-concatenation of _s_ and *"[1]"*. - 1. Else, return _s_. + 1. If _v_ is a String, then + 1. Let _valueStr_ be _v_. + 1. Else if _v_ is a Number, then + 1. Let _valueStr_ be Number::toString(_v_, 10). 1. Else, - 1. Return the string-concatenation of _s_, *"["*, _u_, and *"]"*. + 1. Assert: _v_ is a BigInt. + 1. Let _valueStr_ be BigInt::toString(_v_, 10). + 1. If _u_ is *undefined*, return the string-concatenation of _valueStr_ and *"[]"*. + 1. Return the string-concatenation of _valueStr_, *"["*, _u_, and *"]"*.

Amount.prototype.toLocaleString ( [ _reserved1_ [ , _reserved2_ ] ] )

-

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement this method as specified in the ECMA-402 specification. If an ECMAScript implementation does not include the ECMA-402 API the following specification of this method is used:

-

This method produces a String value that represents this Amount object formatted according to the conventions of the host environment’s current locale. This method is implementation-defined, and it is permissible, but not encouraged, for it to return the same thing as `toString`.

-

The meanings of the optional parameters to this method are defined in the ECMA-402 specification; implementations that do not include ECMA-402 support must not use those parameter positions for anything else.

-
- - -

Amount.prototype.with ( _options_ )

-

This method returns a fresh Amount object whose underlying mathematical value is equal to the mathematical value of the current Amount, but possibly with different precision as specified in the _options_.

+

An ECMAScript implementation that includes the ECMA-402 Internationalization API must implement this method as specified in the ECMA-402 specification. If an ECMAScript implementation does not include the ECMA-402 API the following specification of this method is used:

It performs the following steps when called:

1. Let _O_ be the *this* value. - 1. Perform ? RequireInternalSlot(_O_, [[Unit]]). - 1. Perform ? RequireInternalSlot(_O_, [[Value]]). - 1. Let _processedOptions_ be ? GetAmountOptions(_options_). - 1. Let _unit_ be _processedOptions_.[[Unit]]. - 1. Let _fractionDigits_ be _processedOptions_.[[FractionDigits]]. - 1. Let _significantDigits_ be _processedOptions_.[[SignificantDigits]]. - 1. Let _value_ be _O_.[[Value]]. - 1. If _significantDigits_ is not *undefined*, set _fractionDigits_ to SignificantToFractionDigits(_value_, _significantDigits_). - 1. If _fractionDigits_ is not *undefined*, set _value_ to RoundAmountValueToFractionDigits(_value_, _fractionDigits_). - 1. Let _N_ be OrdinaryObjectCreate(*"%Amount.prototype%"*, « [[FractionDigits]], [[Unit]], [[Value]] »). - 1. If _unit_ is not *undefined* and _O_.[[Unit]] is not *undefined*, then - 1. If SameValueNonNumber(_unit_, _O_.[[Unit]]) is *false*, throw a *TypeError* exception. - 1. Set _N_.[[Value]] to _value_. - 1. Set _N_.[[Unit]] to _unit_. - 1. Set _N_.[[FractionDigits]] to ℝ(_fractionDigits_). - 1. Return _N_. + 1. Perform ? RequireInternalSlot(_O_, [[AmountValue]]). + 1. Return ? Call(%Amount.prototype.toString%, _O_, « »). +

The meanings of the optional parameters to this method are defined in the ECMA-402 specification; implementations that do not include ECMA-402 support must not use those parameter positions for anything else.

- -

Amount.prototype [ %Symbol.toPrimitive% ] ( _hint_ )

-

This method is called by ECMAScript language operators to convert an Amount to a primitive value. The allowed values are *"default"*, *"number"*, and *"string"*. The default is *"number."*

+ +

Amount.prototype.convertTo ( _options_ )

+

This method returns a new Amount whose value is the result of converting this Amount’s value from its current unit to a target unit. The target unit is specified by _options_.

It performs the following steps when called:

- 1. Let _O_ be the the *this* value. - 1. Perform ? RequireInternalSlot(_O_, [[Value]]). - 1. Perform ? RequireInternalSlot(_O_, [[FractionDigits]]). - 1. Perform ? RequireInternalSlot(_O_, [[Unit]]). - 1. If _hint_ is not in « *"default"*, *"number"*, *"string"* », throw a *RangeError* exception. - 1. Let _unit_ be _O_.[[Unit]]. - 1. Let _mv_ be _O_.[[Value]]. - 1. If _hint_ is *"string"*, then - 1. Return ! Call(%Amount.prototype.toString%, _O_, « »). + 1. Let _O_ be the *this* value. + 1. Perform ? RequireInternalSlot(_O_, [[AmountValue]]). + 1. Let _sourceUnit_ be _O_.[[Unit]]. + 1. If _sourceUnit_ is *undefined*, throw a *TypeError* exception. + 1. Let _validatedOpts_ be ? GetAmountConvertToOptions(_options_). + 1. Let _targetUnit_ be _validatedOpts_.[[Unit]]. + 1. If _targetUnit_ is *undefined*, throw a *TypeError* exception. + 1. Let _roundingMode_ be _validatedOpts_.[[RoundingMode]]. + 1. Let _roundingPriority_ be _validatedOpts_.[[RoundingPriority]]. + 1. Let _minFractionDigits_ be _validatedOpts_.[[MinimumFractionDigits]]. + 1. Let _maxFractionDigits_ be _validatedOpts_.[[MaximumFractionDigits]]. + 1. Let _minSignificantDigits_ be _validatedOpts_.[[MinimumSignificantDigits]]. + 1. Let _maxSignificantDigits_ be _validatedOpts_.[[MaximumSignificantDigits]]. + 1. Let _v_ be _O_.[[AmountValue]]. + 1. If _v_ is a Number, then + 1. Let _sourceValue_ be _v_. + 1. Else if _v_ is a BigInt, then + 1. Let _sourceValue_ be 𝔽(ℝ(_v_)). 1. Else, - 1. If _unit_ is not *undefined*, throw a *TypeError* exception. - 1. Return the Number value for _mv_. + 1. Assert: _v_ is a String. + 1. Let _sourceValue_ be StringToNumber(_v_). + 1. Let _convertedValue_ be ? ConvertUnitValue(_sourceValue_, _sourceUnit_, _targetUnit_). + 1. TODO Let _intlObject_ be an Object suitable as the first argument of FormatNumericToString, using _minFractionDigits_, _maxFractionDigits_, _minSignificantDigits_, _maxSignificantDigits_, _roundingPriority_, and _roundingMode_. + 1. Let _formatted_ be FormatNumericToString(_intlObject_, _convertedValue_, 0). + 1. Let _result_ be OrdinaryObjectCreate(%Amount.prototype%, « [[AmountValue]], [[Unit]] »). + 1. Set _result_.[[AmountValue]] to _formatted_.[[FormattedString]]. + 1. Set _result_.[[Unit]] to _targetUnit_. + 1. Return _result_. + +

An ECMAScript implementation that includes the ECMA-402 Internationalization API supersedes this method to additionally support locale-based and usage-based unit conversion via CLDR unit preferences data. Without ECMA-402, only explicit unit-to-unit conversion (via the *"unit"* option) is supported.

+
+ + +

Normative References

+ +