-
Notifications
You must be signed in to change notification settings - Fork 169
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
base: main
Are you sure you want to change the base?
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3130 +/- ##
=======================================
Coverage 96.78% 96.78%
=======================================
Files 21 21
Lines 10003 10003
Branches 1830 1830
=======================================
Hits 9681 9681
Misses 276 276
Partials 46 46 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
70fa5fa
to
b3f6a0f
Compare
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 (as noted previously, there doesn't appear to be Test262 coverage for this) |
There was a problem hiding this 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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is roughly what I was imagining, thanks for doing all this work!
As Richard has noted, handling unset/default values may be tricky. The way I was expecting it to work was that the get allows you to specify REQUIRED, and Validate doesn't need to care, which roughly appears to be what you're doing here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm surprised that this didn't show up in more places. But I guess smallestUnit
is often the last option read anyway, because S is relatively late in the alphabet. So I'm pleasantly surprised at the small extent of the normative change. (I am assuming this PR is the full extent of the changes!)
All in all I'd still prefer not to do this. (It isn't a bug in the proposal, it sets a new precedent that TC39 hasn't really shown appetite for so far, and I just don't see the alternative workaround in temporal_rs as that big of a deal.) But it's small and targeted enough that if I'm the only opposing voice, I won't stand in the way.
Logistical note: to make the best impression when presenting to TC39, I'd recommend squashing the fixup commits into their appropriate editorial or normative commits, then splitting out the editorial commit into its own PR which I can review quickly and merge. That way, there's less for delegates to review and it's much clearer what is changing.
This PR fixes the issues involving unit-valued options, which is the current scope of the issue and all I'm asking for at this time. Yes, often smallestUnit is the final read, so no change was needed in those cases. Yes, splitting the editorial change into its own PR is something I'm happy to do. |
@anba Do you have any concerns about this change? |
I opened #3135 for the editorial changes. |
The editorial changes are merged, and I rebased this. So now it's just the minimal set of normative changes. |
I don't think so. It'll require some small refactoring because the current SM implementation sometimes uses (The SM implementation already parses the unit options accepting all units and only later check which units are actually allowed. ) |
I wonder is there a difference between "Get-Cast-Get-Cast-Validate" and "Get-Get-Cast-Cast-Validate" |
Yes, there is, the Get step may fail if the object has an accessor property, and the Cast step may fail if the property is of the wrong type, so it's observable. |
I'd like to write test262 tests for this before merging it, because it's not covered at all. To that end, it'd be helpful if #3142 could be reviewed and merged first, as it contains the updates to the reference code for the editorial changes. |
I'd like to know why you chose "Get-Cast-Get-Cast-Validate", not "Get-Get-Cast-Cast-Validate". Is there a difference between them when making a fast implementation? If there is no difference, "Get-Get-Cast-Cast-Validate" looks clearer to me. |
The thinking was that Get and Cast are both steps that deeply involve the JS bindings, a layer above the library boundary, whereas Validate is on the library layer. Also, the champions didn't want to make a large change, and Get Get Cast Cast would involve rewriting all call sites of GetOption. |
1. Let _relativeToRecord_ be ? GetTemporalRelativeToOption(_roundTo_). | ||
1. Let _zonedRelativeTo_ be _relativeToRecord_.[[ZonedRelativeTo]]. | ||
1. Let _plainRelativeTo_ be _relativeToRecord_.[[PlainRelativeTo]]. | ||
1. Let _roundingIncrement_ be ? GetRoundingIncrementOption(_roundTo_). | ||
1. Let _roundingMode_ be ? GetRoundingModeOption(_roundTo_, ~half-expand~). | ||
1. Let _smallestUnit_ be ? GetTemporalUnitValuedOption(_roundTo_, *"smallestUnit"*, ~unset~). | ||
1. Perform ? ValidateTemporalUnitValue(_largestUnit_, ~datetime~, « ~auto~ »). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it actually the case that this is a no-op? GetTemporalUnitValuedOption can return any unit, AUTO, or UNSET. And this particular invocation of ValidateTemporalUnitValue permits any unit, AUTO, or UNSET.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since ~datetime~
is the superset of all units, then your observation seems correct
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