Skip to content

Observable validation logic #92

@gibson042

Description

@gibson042

It's a bit strange that e.g. GetAmountOptions rejects an invalid roundingMode value such as "foo" before even attempting to [[Get]] unit, but does not reject an invalid numeric fractionDigits such as 4.2 until after [[Get]]ing all options fields and verifying absence of a non-undefined value for significantDigits. I think it would make more sense (and be more aligned with recent additions such as Temporal) to perform isolated validation atomically with each [[Get]], leaving the door open for future consolidation that extends/wraps/post-processes GetOption similar to GetNumberOption, DefaultNumberOption, ToIntegerIfIntegral, and GetRoundingIncrementOption:

@@ GetAmountOptions (
           1. Let _opts_ be ? GetOptionsObject(_opts_).
           1. Let _fractionDigits_ be ? GetOption(_opts_, *"fractionDigits"*, ~number~, ~empty~, *undefined*).
+          1. If _fractionDigits_ is not *undefined* and not an integral Number, throw a *RangeError* exception.
           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. If _significantDigits_ is not *undefined* and not a positive integral Number, throw a *RangeError* exception.
           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_ &lt; *1*<sub>𝔽</sub>, throw a *RangeError* exception.
           1. If _unit_ is the empty String, throw a *RangeError* exception.
+          1. If _fractionDigits_ is not *undefined* and _significantDigits_ is not *undefined*, throw a *TypeError* exception.
           1. Return the Record { [[FractionDigits]]: _fractionDigits_, [[RoundingMode]]: _roundingMode_, [[SignificantDigits]]: _significantDigits_, [[Unit]]: _unit_ }.
@@ GetAmountConvertToOptions (
           1. Let _opts_ be ? GetOptionsObject(_opts_).
-          1. Let _minFractionDigits_ be ? GetOption(_opts_, *"minimumfractionDigits"*, ~number~, ~empty~, *undefined*).
+          1. Let _minFractionDigits_ be ? GetOption(_opts_, *"minimumFractionDigits"*, ~number~, ~empty~, *undefined*).
+          1. If _minFractionDigits_ is not *undefined* and not an integral Number, throw a *RangeError* exception.
-          1. Let _maxFractionDigits_ be ? GetOption(_opts_, *"maximumfractionDigits"*, ~number~, ~empty~, *undefined*).
+          1. Let _maxFractionDigits_ be ? GetOption(_opts_, *"maximumFractionDigits"*, ~number~, ~empty~, *undefined*).
+          1. If _maxFractionDigits_ is not *undefined* and not an integral Number, throw a *RangeError* exception.
           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. If _minSignificantDigits_ is not *undefined* and not an integral Number, throw a *RangeError* exception.
           1. Let _maxSignificantDigits_ be ? GetOption(_opts_, *"maximumSignificantDigits"*, ~number~, ~empty~, *undefined*).
+          1. If _maxSignificantDigits_ is not *undefined* and not an integral Number, throw a *RangeError* exception.
-          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_ }.
+          1. Return the Record { [[MinimumFractionDigits]]: _minFractionDigits_, [[MaximumFractionDigits]]: _maxFractionDigits_, [[MinimumSignificantDigits]]: _minSignificantDigits_, [[MaximumSignificantDigits]]: _maxSignificantDigits_, [[RoundingMode]]: _roundingMode_, [[RoundingPriority]]: _roundingPriority_, [[Unit]]: _unit_ }.

(note also the alias/property key spelling corrections, removal of [[SignificantDigits]], and replacement of RangeError with TypeError to indicate conflicting options, aligning with e.g. CreateDateTimeFormat and SetNumberFormatDigitOptions)

Further, options should be read in alphabetical order, reording GetAmountConvertToOptions like ["maximumFractionDigits", "maximumSignificantDigits", "minimumFractionDigits", "minimumSignificantDigits", "roundingMode", "roundingPriority"].

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions