-
Notifications
You must be signed in to change notification settings - Fork 158
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
Problem with generating Durations from non-numeric input components #2112
Comments
I find this consistent with how coercion to a number usually works in JS: [1, 2, 3].slice(Symbol()) // TypeError
[1, 2, 3].slice(NaN) // => [1, 2, 3]
[1, 2, 3].slice("foo") // => [1, 2, 3]
[1, 2, 3].slice(/regex/) // => [1, 2, 3]
[1, 2, 3].slice(Math) // => [1, 2, 3] Not that I think the status quo is the best choice that could've been made, but it doesn't seem good to me to deviate from it now. |
I think "usually" is overly broad there; many operations behave differently: [].length = NaN // RangeError
String.fromCodePoint("foo") // RangeError Particularly some that are closely related to Temporal: new Date(/regex/) // => Invalid Date
Date.UTC(Math) // => NaN And I think this behavior is particularly bad in duration-like objects, where bad data associated with a field is silently ignored unless it is only slightly bad—what is the point of rejecting |
I agree with @gibson042. The fact that some other APIs are bad doesn't mean that new APIs should also be bad. |
I ran across "Fix .at()" with a comment from @bakkot, among others:
|
To be clear, that opinion applies mainly to new functions on existing APIs. I think there's a little more room to provide a better experience on entirely new APIs. I've commented as much on this very similar issue on iterator helpers. |
I took an action in the Temporal champions meeting to informally poll delegates in the Matrix channel to see if this would be contentious at plenary. Before I do that, let's clarify what changes we are taking about here. As I understand it, the suggestion would be to change ToIntegerThrowOnInfinity to look something like this:
And change ToIntegerWithoutRounding to look something like this:
This would mean the following changes in how values would be coerced to mathematical values in Temporal:
Booleans, legacy Dates, and null seem like things that we might consider throwing on as well, here. Note, this would also depart from the WebIDL ConvertToInt algorithm which does the same thing with NaN, unless it is annotated with [EnforceRange]. On the other hand, there is already a precedent because all public entry points to Temporal that expect a number, already go through ToIntegerThrowOnInfinity, ToPositiveInteger, or ToIntegerWithoutRounding, and not through ToIntegerOrInfinity, so we already throw on infinities where other entry points don't. |
Note that this also might apply to entry points like |
@ptomato I agree with your assessment, and support the changes described therein. I would also include some preceding refactorings for clarity:
|
I think I'd prefer if the operations still all start with "To" similar to most other type conversion operations. ( |
I want these names to not start with "To" precisely because the behavior is dissimilar from operations with that prefix—unlike e.g. ToNumber and ToIntegerOrInfinity and ToLength |
ToIndex throws for out-of-range values: |
OK, I'll do the informal poll once I have cleared out a bit more of my backlog of notifications from while I was away. I don't have an opinion on the names of the operations. (Except that I find "InsistInteger" slightly ungrammatical) |
In case it helps, in modern Web IDL we suggest people use basically these types: |
Picking this up again; the discussion hasn't moved forward in the meantime, but maybe it will help if we have a proof of concept to discuss. I'll start with an editorial PR renaming the operations without changing any of the behaviour, then create a proof of concept for the behaviour change. As for renaming, I started with TruncateToInteger, but after trying it out I have to agree with @anba that it should start with "To"; TruncateToInteger sounds like it's meant to operate only on a mathematical value. How about this bikeshed?
|
I've looked into the Web IDL conversion algorithms and for our purposes it looks like the closest equivalent would be
Re. 1), I'm not sure of the reason that Web IDL chooses TypeError for out-of-range values rather than RangeError, but it seems more usual within ECMA-262 to use RangeError here. Changing 2) is something that could make sense. IIRC we have Re. 3), the throw-instead-of-truncate behaviour for Duration is well-motivated in my opinion and has already been discussed extensively elsewhere. |
The editorial PR: #2430 |
In the Temporal champions meeting of 2022-10-27, we reached an agreement on this. Regarding Web IDL throwing on converting undefined to an integer, Richard noted that the overload resolution algorithm in Web IDL treats undefined/absent values for optional arguments differently from required arguments. e.g., The consensus is that we will proceed with the above table, with one change to align better with Web IDL: converting undefined to an integer will throw RangeError rather than resulting in 0. Optional arguments with default values will "override" undefined with the default value. So, concretely,
|
NaN
is replaced with zero by ToIntegerWithoutRounding step 2, but this leads to some surprising and IMO bad consequences:The text was updated successfully, but these errors were encountered: