diff --git a/README.md b/README.md index 9418c05..8a4e3ee 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Representing Amounts -**Stage**: 1 +**Stage**: 2 **Champion**: Jesse Alama [@jessealama](https://github.com/jessealama) diff --git a/index.html b/index.html index 2aab1aa..65a856b 100644 --- a/index.html +++ b/index.html @@ -874,7 +874,7 @@ this.$pane.appendChild(this.$tableContainer); if (menu != null) { - menu.$specContainer.after(this.$container); + menu.$specContainer.appendChild(this.$container); } }, @@ -1206,9 +1206,6 @@ document.documentElement.classList.toggle('show-ao-annotations'); } else if (e.key === '?') { document.getElementById('shortcuts-help').classList.toggle('active'); - } else if (e.key === ';') { - let el = document.getElementById('bd75b99add5f'); - if (el != null) el.remove(); } } @@ -2256,7 +2253,7 @@ } emu-nt { - display: inline-block; + display: inline; font-style: italic; white-space: nowrap; text-indent: 0; @@ -2596,7 +2593,7 @@ } emu-table td { - background: transparent; + background: var(--background-color); } td[colspan]:not([colspan="1"]), th[colspan]:not([colspan="1"]) { @@ -2703,7 +2700,7 @@ height: 100vh; max-width: 500px; box-sizing: border-box; - background: var(--control-background-color); + background-color: var(--control-background-color); overflow: hidden; transition: opacity 0.1s linear; padding: 0 5px; @@ -3144,7 +3141,7 @@ .toolbox::after { border-color: var(--toolbox-tail-background-outside-color); - border-top-color: var(--control-border-color); + border-top-color: var(--control-background-color); border-width: 10px; margin-left: -10px; } @@ -3161,7 +3158,7 @@ left: 0; right: 0; display: none; - background: var(--control-background-color); + background-color: var(--control-background-color); z-index: 1; } @@ -3202,17 +3199,6 @@ padding-right: 5px; } -emu-normative-optional { - display: block; -} - -emu-normative-optional::before { - display: block; - color: var(--attributes-tag-foreground-color); - content: "NORMATIVE OPTIONAL"; -} - -emu-normative-optional, [normative-optional], [deprecated], [legacy] { @@ -3245,7 +3231,7 @@ outline: solid 10000px var(--control-dialog-fade-color); border-radius: 5px; border-width: 1px 1px 0 1px; - background: var(--control-background-color); + background-color: var(--control-background-color); display: none; } @@ -3551,18 +3537,6 @@ break-after: initial; /* it's okay to break after the last item in a list, even if it's also the first item in the list */ } -emu-normative-optional { - break-inside: avoid; -} - -emu-normative-optional emu-clause[id] { - margin-top: 0; -} - -emu-normative-optional emu-alg > ol { - margin-bottom: 0; -} - emu-note { gap: initial; justify-content: space-between; @@ -3994,7 +3968,7 @@

Stage 1 Draft / May 20, 2026

Amount

+

Stage 2 Draft / May 20, 2026

Amount

Introduction

@@ -4037,13 +4011,13 @@

1.1.1 GetOption ( options, prope

1.1.2 GetAmountOptions ( opts )

The abstract operation GetAmountOptions takes argument opts (an Object) and returns 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. 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 performs the following steps when called:

-
  1. Let opts be ? GetOptionsObject(opts).
  2. Let fractionDigits be ? GetOption(opts, "fractionDigits", number, empty, undefined).
  3. Let roundingMode be ? GetOption(opts, "roundingMode", string, « "ceil", "floor", "expand", "trunc", "halfCeil", "halfFloor", "halfExpand", "halfTrunc", "halfEven" », "halfEven").
  4. Let significantDigits be ? GetOption(opts, "significantDigits", number, empty, undefined).
  5. Let unit be ? GetOption(opts, "unit", string, empty, undefined).
  6. If fractionDigits is not undefined, then
    1. If significantDigits is not undefined, throw a RangeError exception.
    2. If fractionDigits is not an integral Number, throw a RangeError exception.
    3. Set fractionDigits to (fractionDigits).
    4. If fractionDigits is not in the inclusive interval from 0 to 100, throw a RangeError exception.
  7. Else if significantDigits is not undefined, then
    1. If significantDigits is not an integral Number, throw a RangeError exception.
    2. Set significantDigits to (significantDigits).
    3. If significantDigits is not in the inclusive interval from 1 to 21, throw a RangeError exception.
  8. If unit is the empty String, throw a RangeError exception.
  9. Return the Record { [[FractionDigits]]: fractionDigits, [[RoundingMode]]: roundingMode, [[SignificantDigits]]: significantDigits, [[Unit]]: unit }.
+
  1. Let opts be ? GetOptionsObject(opts).
  2. Let fractionDigits be ? GetOption(opts, "fractionDigits", number, empty, undefined).
  3. Let roundingMode be ? GetOption(opts, "roundingMode", string, « "ceil", "floor", "expand", "trunc", "halfCeil", "halfFloor", "halfExpand", "halfTrunc", "halfEven" », "halfEven").
  4. Let significantDigits be ? GetOption(opts, "significantDigits", number, empty, undefined).
  5. Let unit be ? GetOption(opts, "unit", string, empty, undefined).
  6. If fractionDigits is not undefined, then
    1. If significantDigits is not undefined, throw a RangeError exception.
    2. If fractionDigits is not an integral Number, throw a RangeError exception.
    3. Set fractionDigits to (fractionDigits).
    4. If fractionDigits is not in the inclusive interval from 0 to 100, throw a RangeError exception.
  7. Else if significantDigits is not undefined, then
    1. If significantDigits is not an integral Number, throw a RangeError exception.
    2. Set significantDigits to (significantDigits).
    3. If significantDigits is not in the inclusive interval from 1 to 21, throw a RangeError exception.
  8. If unit is the empty String, throw a RangeError exception.
  9. Return the Record { [[FractionDigits]]: fractionDigits, [[RoundingMode]]: roundingMode, [[SignificantDigits]]: significantDigits, [[Unit]]: unit }.

1.1.3 GetAmountConvertToOptions ( opts )

The abstract operation GetAmountConvertToOptions takes argument opts (an Object) and returns 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. 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). It performs the following steps when called:

-
  1. Let opts be ? GetOptionsObject(opts).
  2. Let fractionDigits be ? GetOption(opts, "fractionDigits", number, empty, undefined).
  3. Let roundingMode be ? GetOption(opts, "roundingMode", string, « "ceil", "floor", "expand", "trunc", "halfCeil", "halfFloor", "halfExpand", "halfTrunc", "halfEven" », "halfEven").
  4. Let significantDigits be ? GetOption(opts, "significantDigits", number, empty, undefined).
  5. Let unit be ? GetOption(opts, "unit", string, empty, undefined).
  6. If fractionDigits is not undefined, then
    1. If significantDigits is not undefined, throw a RangeError exception.
    2. If fractionDigits is not an integral Number, throw a RangeError exception.
    3. Set fractionDigits to (fractionDigits).
    4. If fractionDigits is not in the inclusive interval from 0 to 100, throw a RangeError exception.
  7. Else if significantDigits is not undefined, then
    1. If significantDigits is not an integral Number, throw a RangeError exception.
    2. Set significantDigits to (significantDigits).
    3. If significantDigits is not in the inclusive interval from 1 to 21, throw a RangeError exception.
  8. If unit is the empty String, throw a RangeError exception.
  9. Return the Record { [[FractionDigits]]: fractionDigits, [[RoundingMode]]: roundingMode, [[SignificantDigits]]: significantDigits, [[Unit]]: unit }.
+
  1. Let opts be ? GetOptionsObject(opts).
  2. Let fractionDigits be ? GetOption(opts, "fractionDigits", number, empty, undefined).
  3. Let roundingMode be ? GetOption(opts, "roundingMode", string, « "ceil", "floor", "expand", "trunc", "halfCeil", "halfFloor", "halfExpand", "halfTrunc", "halfEven" », "halfEven").
  4. Let significantDigits be ? GetOption(opts, "significantDigits", number, empty, undefined).
  5. Let unit be ? GetOption(opts, "unit", string, empty, undefined).
  6. If fractionDigits is not undefined, then
    1. If significantDigits is not undefined, throw a RangeError exception.
    2. If fractionDigits is not an integral Number, throw a RangeError exception.
    3. Set fractionDigits to (fractionDigits).
    4. If fractionDigits is not in the inclusive interval from 0 to 100, throw a RangeError exception.
  7. Else if significantDigits is not undefined, then
    1. If significantDigits is not an integral Number, throw a RangeError exception.
    2. Set significantDigits to (significantDigits).
    3. If significantDigits is not in the inclusive interval from 1 to 21, throw a RangeError exception.
  8. If unit is the empty String, throw a RangeError exception.
  9. Return the Record { [[FractionDigits]]: fractionDigits, [[RoundingMode]]: roundingMode, [[SignificantDigits]]: significantDigits, [[Unit]]: unit }.
@@ -4089,7 +4063,7 @@

1.1.7 GetUnitConversionFactor ( unit

1.1.8 ConvertUnitValue ( value, sourceUnit, targetUnit )

The abstract operation ConvertUnitValue takes arguments value (a Number), sourceUnit (a String), and targetUnit (a String) and returns either a normal completion containing a Number or a throw completion. It converts value from sourceUnit to targetUnit using Number arithmetic. It performs the following steps when called:

-
  1. If SameValue(sourceUnit, targetUnit) is true, return value.
  2. Let sourceConv be ? GetUnitConversionFactor(sourceUnit).
  3. Let targetConv be ? GetUnitConversionFactor(targetUnit).
  4. If sourceConv.[[BaseUnit]] is not targetConv.[[BaseUnit]], throw a TypeError exception.
  5. If value is NaN, return NaN.
  6. Let sourceFactor be sourceConv.[[Factor]].
  7. Let sourceOffset be sourceConv.[[Offset]].
  8. Let targetFactor be targetConv.[[Factor]].
  9. Let targetOffset be targetConv.[[Offset]].
  10. If sourceOffset is targetOffset, then
    1. NOTE: This preserves a value of -0𝔽.
    2. Return value × 𝔽(sourceFactor / targetFactor).
  11. Return value × 𝔽(sourceFactor / targetFactor) + 𝔽((sourceOffset - targetOffset) / targetFactor).
+
  1. If SameValue(sourceUnit, targetUnit) is true, return value.
  2. Let sourceConv be ? GetUnitConversionFactor(sourceUnit).
  3. Let targetConv be ? GetUnitConversionFactor(targetUnit).
  4. If sourceConv.[[BaseUnit]] is not targetConv.[[BaseUnit]], throw a TypeError exception.
  5. If value is NaN, return NaN.
  6. Let sourceFactor be sourceConv.[[Factor]].
  7. Let sourceOffset be sourceConv.[[Offset]].
  8. Let targetFactor be targetConv.[[Factor]].
  9. Let targetOffset be targetConv.[[Offset]].
  10. If sourceOffset is targetOffset, then
    1. NOTE: This preserves a value of -0𝔽.
    2. Return value × 𝔽(sourceFactor / targetFactor).
  11. Return value × 𝔽(sourceFactor / targetFactor) + 𝔽((sourceOffset - targetOffset) / targetFactor).
Note

The factor term sourceFactor / targetFactor and the offset term (sourceOffsettargetOffset) / targetFactor are computed as mathematical values, and then converted to Number values for the multiplication and addition. For non-offset conversions (the vast majority), the offset term is 0 and addition is skipped in order to preserve an input value of -0𝔽.

@@ -4181,7 +4155,7 @@

3.1.1 Amount.prototype.toLocaleString ( [ l

This function performs the following steps when called:

-
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[AmountValue]]).
  3. Let v be O.[[AmountValue]].
  4. If v is a String, then
    1. Let numValue be v.
  5. Else if v is a BigInt, then
    1. Let numValue be BigInt::toString(v, 10).
  6. Else,
    1. Assert: v is a Number.
    2. Let numValue be v.
  7. Let unit be O.[[Unit]].
  8. Let mergedOptions be OrdinaryObjectCreate(null).
  9. If options is not undefined, then
    1. Let optionsObj be ? GetOptionsObject(options).
    2. Perform ? CopyDataProperties(mergedOptions, optionsObj, « »).
  10. 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").
        2. If ? HasProperty(mergedOptions, "currency") is false, then
          1. Perform ! CreateDataPropertyOrThrow(mergedOptions, "currency", unit).
      2. Else,
        1. Perform ! CreateDataPropertyOrThrow(mergedOptions, "style", "unit").
        2. If ? HasProperty(mergedOptions, "unit") is false, then
          1. Perform ! CreateDataPropertyOrThrow(mergedOptions, "unit", unit).
  11. Let numberFormat be ? Construct(%Intl.NumberFormat%, « locales, mergedOptions »).
  12. Return FormatNumeric(numberFormat, numValue).
+
  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[AmountValue]]).
  3. Let v be O.[[AmountValue]].
  4. If v is a String, then
    1. Let numValue be v.
  5. Else if v is a BigInt, then
    1. Let numValue be BigInt::toString(v, 10).
  6. Else,
    1. Assert: v is a Number.
    2. Let numValue be v.
  7. Let unit be O.[[Unit]].
  8. Let mergedOptions be OrdinaryObjectCreate(null).
  9. If options is not undefined, then
    1. Let optionsObj be ? GetOptionsObject(options).
    2. Perform ? CopyDataProperties(mergedOptions, optionsObj, « »).
  10. 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").
        2. If ? HasProperty(mergedOptions, "currency") is false, then
          1. Perform ! CreateDataPropertyOrThrow(mergedOptions, "currency", unit).
      2. Else,
        1. Perform ! CreateDataPropertyOrThrow(mergedOptions, "style", "unit").
        2. If ? HasProperty(mergedOptions, "unit") is false, then
          1. Perform ! CreateDataPropertyOrThrow(mergedOptions, "unit", unit).
  11. Let numberFormat be ? Construct(%Intl.NumberFormat%, « locales, mergedOptions »).
  12. Return FormatNumeric(numberFormat, numValue).
@@ -4235,7 +4209,7 @@

5 Normative References

Copyright & Software License

Software License

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

diff --git a/spec.emu b/spec.emu index d3671f7..1d8f6a5 100644 --- a/spec.emu +++ b/spec.emu @@ -6,8 +6,8 @@