Skip to content

Normative: Validate unit-valued options after all options are read #3130

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

sffc
Copy link
Collaborator

@sffc sffc commented Jul 11, 2025

See #3116

This preserves the original call to GetOption, but it always calls it with the full list of units, and I pull the subset-checking logic into a separate AO.

I have two commits: an editorial change to split the AO in two, and a small normative change to move the validation later down at the call sites.

@nekevss @Manishearth

@sffc sffc requested a review from ptomato July 11, 2025 00:50
Copy link

codecov bot commented Jul 11, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 96.85%. Comparing base (ed49b0b) to head (09a2390).
Report is 2 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3130   +/-   ##
=======================================
  Coverage   96.85%   96.85%           
=======================================
  Files          21       21           
  Lines        9983     9983           
  Branches     1829     1829           
=======================================
  Hits         9669     9669           
  Misses        268      268           
  Partials       46       46           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@sffc sffc changed the title Normative: Validate Temporal-valued unit options after all options are read Normative: Validate unit-valued options after all options are read Jul 11, 2025
@sffc sffc force-pushed the validate-unit branch 2 times, most recently from 70fa5fa to b3f6a0f Compare July 11, 2025 01:09
@sffc
Copy link
Collaborator Author

sffc commented Jul 11, 2025

The code that changes behavior with this PR is something like:

obj = {
    get largestUnit() {
        console.log("get largestUnit");
        return "years";
    },
    get smallestUnit() {
        console.log("get smallestUnit");
        return "seconds";
    },
}

Temporal.PlainTime.from("00:00").round(obj)

Current behavior: console logs "get largestUnit" and then RangeError is thrown.

New behavior: console logs both "get largestUnit" and "get smallestUnit", and then RangeError is thrown.

Note: the RangeError is because PlainTime does not allow "years" as a largestUnit. There is no difference in behavior if get largestUnit() returns an invalid string such as "INVALID".

(as noted previously, there doesn't appear to be Test262 coverage for this)

Copy link
Collaborator

@gibson042 gibson042 left a comment

Choose a reason for hiding this comment

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

The intended changes as I understand them do seem both reasonable and narrow, but I think the algorithms steps fail to properly implement them.

Comment on lines +560 to +561
1. Let _allowedStrings_ be a new empty List.
1. Append *"auto"* to _allowedStrings_.
Copy link
Collaborator

@gibson042 gibson042 Jul 11, 2025

Choose a reason for hiding this comment

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

Suggested simplification:

Suggested change
1. Let _allowedStrings_ be a new empty List.
1. Append *"auto"* to _allowedStrings_.
1. Let _allowedStrings_ be « *"auto"* ».

Comment on lines +592 to +599
1. Let _allowedValues_ be a new empty List.
1. For each row of <emu-xref href="#table-temporal-units"></emu-xref>, except the header row, in table order, do
1. Let _unit_ be the value in the "Value" column of the row.
1. If the "Category" column of the row is ~date~ and _unitGroup_ is ~date~ or ~datetime~, append _unit_ to _allowedValues_.
1. Else if the "Category" column of the row is ~time~ and _unitGroup_ is ~time~ or ~datetime~, append _unit_ to _allowedValues_.
1. If _extraValues_ is present, then
1. Set _allowedValues_ to the list-concatenation of _allowedValues_ and _extraValues_.
1. If _allowedValues_ does not contain _value_, throw a RangeError exception.
Copy link
Collaborator

Choose a reason for hiding this comment

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

I wonder if it makes sense to keep the allowedValues list at all.

Suggested change
1. Let _allowedValues_ be a new empty List.
1. For each row of <emu-xref href="#table-temporal-units"></emu-xref>, except the header row, in table order, do
1. Let _unit_ be the value in the "Value" column of the row.
1. If the "Category" column of the row is ~date~ and _unitGroup_ is ~date~ or ~datetime~, append _unit_ to _allowedValues_.
1. Else if the "Category" column of the row is ~time~ and _unitGroup_ is ~time~ or ~datetime~, append _unit_ to _allowedValues_.
1. If _extraValues_ is present, then
1. Set _allowedValues_ to the list-concatenation of _allowedValues_ and _extraValues_.
1. If _allowedValues_ does not contain _value_, throw a RangeError exception.
1. If _extraValues_ is present and _extraValues_ contains _value_, return ~unused~.
1. Let _category_ be the value in the “Category” column of the row of <emu-xref href="#table-temporal-units"></emu-xref> whose “Value” column contains _value_. If there is no such row, throw a RangeError exception.
1. If _category_ is ~date~ and _unitGroup_ is ~date~ or ~datetime~, return ~unused~.
1. If _category_ is ~time~ and _unitGroup_ is ~time~ or ~datetime~, return ~unused~.
1. Throw a RangeError exception.

Comment on lines +1878 to +1880
1. Perform ? ValidateTemporalUnitValue(_largestUnit_, _unitGroup_).
1. If _largestUnit_ is ~unset~, then
1. Set _largestUnit_ to ~auto~.
Copy link
Collaborator

Choose a reason for hiding this comment

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

This doesn't look right to me... if largestUnit is ~unset~, wouldn't ValidateTemporalUnitValue(largestUnit, unitGroup) have already rejected it?

Suggested change
1. Perform ? ValidateTemporalUnitValue(_largestUnit_, _unitGroup_).
1. If _largestUnit_ is ~unset~, then
1. Set _largestUnit_ to ~auto~.
1. If _largestUnit_ is ~unset~ or ~auto~, set _largestUnit_ to ~auto~.
1. Else, perform ? ValidateTemporalUnitValue(_largestUnit_, _unitGroup_).

And likewise for the other call sites.

Comment on lines +412 to +413
1. Perform ? ValidateTemporalUnitValue(_largestUnit_, ~datetime~, « ~auto~ »).
1. Perform ? ValidateTemporalUnitValue(_smallestUnit_, ~datetime~).
Copy link
Collaborator

Choose a reason for hiding this comment

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

As noted above, it seems like these calls will reject ~unset~ values.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants