-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
MakeDay should be more explicit how unreasonably large numbers are handled #1087
Comments
cc @gibson042 |
Engine inconsistency confirmed; I'm willing to categorize it into three behaviors (V8/XS vs. SM/Chakra vs. JSC):
As for the spec, MakeDay( year, month, date ) step 7 relies on two mathematical integers derived from combining integer Number interpretations of year and month—ym (a whole number of years after 1 BCE) and mn (a positive number of months in the year corresponding with ym)—and calls for returning NaN unless a corresponding value (time value?) t exists. Time values are bounded to be safe integers in the inclusive range ±8.64e15 ("approximately I like the spec result for the second case, but to be honest, I don't like the bounds clipping implicit in the calls of step 7 because it doesn't incorporate the date argument (resulting in strange behavior for e.g. |
Would you be willing to prepare a PR, and present it at an upcoming meeting for consensus? 🙏 |
Great work, thanks for this analysis. I'd rather avoid using mathematical values in the ECMAScript specification as much as possible, and move towards using Number internally or, in the future, BigInt, when possible. This is the direction of #1135 . I don't know of anything which could produce a valid Date which would rely on calculations outside of Number range. What are the downsides of standardizing the XS/V8 semantics? |
In this case, a mathematical treatment can be defined in terms of BigInt.
I'm not sure what those semantics are. |
It turns out that new test cases and/or spec text are also needed for existing MakeTime IEEE 754-2008 binary64 semantics: Input that cancels out (JSC fails)
Input that cancels out with rounding (JSC and XS fail)
Input that cancels out and then comes in at the time value limit (JSC fails)
Input that cancels out and then exceeds the time value limit (all pass)
Input that exceeds the Number range and unsuccessfully attempts to cancel out (all pass)
Input where MakeTime exceeds the Number range only when considered independently from MakeDay (all pass)
Input where MakeDay and MakeTime cancel out (JSC and XS fail)
|
This is relevant even when not using out-of-range For example, Step 8 of MakeDay requires finding a finite time value t such that YearFromTime(t) = -271821, MonthFromTime(t) = 3, and DateFromTime(t) = 1. No such time value exists. Its Number counterpart would be -8640001641600000, in other words the earliest time value minus 19 days. I think #1564 would solve this, but at the very least MakeDay shoudn't return a time value. |
We must avoid calling GetUTCEpochNanoseconds with dates that are too large because it is ill-defined in ECMA-262 what is supposed to happen. (See tc39/ecma262#1087). We had a condition in ToTemporalInstant that was supposed to prevent this, but was incorrect because subtracting the UTC offset could push the date out of range. Note that this is editorial, because IsValidEpochNanoseconds would throw anyway in this case even if GetUTCEpochNanoseconds was fully defined for large inputs. See: #2985
Similarly to the previous commit, we must avoid calling GetUTCEpochNanoseconds with dates that are too large because it is ill-defined in ECMA-262 what is supposed to happen. (See tc39/ecma262#1087). Previously to PR #2925, that could not happen because GetPossibleInstantsFor took a PlainDateTime object, but now it takes an ISO Date-Time Record. Note that this is editorial, because IsValidEpochNanoseconds would throw anyway in this case even if GetUTCEpochNanoseconds was fully defined for large inputs.
We must avoid calling GetUTCEpochNanoseconds with dates that are too large because it is ill-defined in ECMA-262 what is supposed to happen. (See tc39/ecma262#1087). We had a condition in ToTemporalInstant that was supposed to prevent this, but was incorrect because subtracting the UTC offset could push the date out of range. Note that this is editorial, because IsValidEpochNanoseconds would throw anyway in this case even if GetUTCEpochNanoseconds was fully defined for large inputs. See: #2985
Similarly to the previous commit, we must avoid calling GetUTCEpochNanoseconds with dates that are too large because it is ill-defined in ECMA-262 what is supposed to happen. (See tc39/ecma262#1087). Previously to PR #2925, that could not happen because GetPossibleInstantsFor took a PlainDateTime object, but now it takes an ISO Date-Time Record. Note that this is editorial, because IsValidEpochNanoseconds would throw anyway in this case even if GetUTCEpochNanoseconds was fully defined for large inputs.
Similarly to the previous commit, we must avoid calling GetUTCEpochNanoseconds with dates that are too large because it is ill-defined in ECMA-262 what is supposed to happen. (See tc39/ecma262#1087). Previously to PR #2925, that could not happen because we used a PlainDateTime object in InterpretISODateTimeOffset, but now we use an ISO Date-Time Record. Note that this is editorial, because IsValidEpochNanoseconds would throw anyway in this case even if GetUTCEpochNanoseconds was fully defined for large inputs.
We must avoid calling GetUTCEpochNanoseconds with dates that are too large because it is ill-defined in ECMA-262 what is supposed to happen. (See tc39/ecma262#1087). We had a condition in ToTemporalInstant that was supposed to prevent this, but was incorrect because subtracting the UTC offset could push the date out of range. Note that this is editorial, because IsValidEpochNanoseconds would throw anyway in this case even if GetUTCEpochNanoseconds was fully defined for large inputs. See: #2985
Similarly to the previous commit, we must avoid calling GetUTCEpochNanoseconds with dates that are too large because it is ill-defined in ECMA-262 what is supposed to happen. (See tc39/ecma262#1087). Previously to PR #2925, that could not happen because GetPossibleInstantsFor took a PlainDateTime object, but now it takes an ISO Date-Time Record. Note that this is editorial, because IsValidEpochNanoseconds would throw anyway in this case even if GetUTCEpochNanoseconds was fully defined for large inputs.
Similarly to the previous commit, we must avoid calling GetUTCEpochNanoseconds with dates that are too large because it is ill-defined in ECMA-262 what is supposed to happen. (See tc39/ecma262#1087). Previously to PR #2925, that could not happen because we used a PlainDateTime object in InterpretISODateTimeOffset, but now we use an ISO Date-Time Record. Note that this is editorial, because IsValidEpochNanoseconds would throw anyway in this case even if GetUTCEpochNanoseconds was fully defined for large inputs.
This pattern is there because of #2729 and #2985. Abstract it into its own operation, for documentation purposes and because it can disappear after tc39/ecma262#1087 is fixed. See: #3005
This pattern is there because of #2729 and #2985. Abstract it into its own operation, for documentation purposes and because it can disappear after tc39/ecma262#1087 is fixed. See: #3005
20.3.1.12 MakeDay should use a more precise language than "[...] but if this is not possible (because some argument is out of range), return NaN.". For example 20.3.1.11 MakeTime explicitly requires to use IEEE 754-2008 semantics for its operations.
This test prints different results in all four engines (SpiderMonkey and ChakraCore are almost the same, except Chakra prints the year as "-0000" for the second date, but that's probably a different issue) and I blame it one the imprecise language. 😛
The text was updated successfully, but these errors were encountered: