<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE bugzilla SYSTEM "https://bugs.webkit.org/page.cgi?id=bugzilla.dtd">

<bugzilla version="5.0.4.1"
          urlbase="https://bugs.webkit.org/"
          
          maintainer="admin@webkit.org"
>

    <bug>
          <bug_id>238050</bug_id>
          
          <creation_ts>2022-03-17 15:29:39 -0700</creation_ts>
          <short_desc>[JSC] Change Date.parse to stop returning numbers with fractional part</short_desc>
          <delta_ts>2022-03-23 16:32:06 -0700</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>1</classification_id>
          <classification>Unclassified</classification>
          <product>WebKit</product>
          <component>JavaScriptCore</component>
          <version>WebKit Nightly Build</version>
          <rep_platform>Unspecified</rep_platform>
          <op_sys>Unspecified</op_sys>
          <bug_status>RESOLVED</bug_status>
          <resolution>FIXED</resolution>
          
          
          <bug_file_loc></bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords>InRadar</keywords>
          <priority>P2</priority>
          <bug_severity>Normal</bug_severity>
          <target_milestone>---</target_milestone>
          
          
          <everconfirmed>1</everconfirmed>
          <reporter name="Richard Gibson">richard.gibson</reporter>
          <assigned_to name="Yusuke Suzuki">ysuzuki</assigned_to>
          <cc>ews-watchlist</cc>
    
    <cc>keith_miller</cc>
    
    <cc>mark.lam</cc>
    
    <cc>msaboff</cc>
    
    <cc>saam</cc>
    
    <cc>tzagallo</cc>
    
    <cc>webkit-bug-importer</cc>
    
    <cc>ysuzuki</cc>
          

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>1852519</commentid>
    <comment_count>0</comment_count>
    <who name="Richard Gibson">richard.gibson</who>
    <bug_when>2022-03-17 15:29:39 -0700</bug_when>
    <thetext>JavaScriptCore `Date.parse` can return non-integer non-NaN numbers, in violation of https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-date.parse (which requires the output to be a _time value_—&quot;either a finite **integral Number** representing an instant in time to millisecond precision or NaN representing no specific instant&quot; [cf. https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-time-values-and-time-range ]):
```sh
$ eshost -se &apos;
  [
    &quot;1970-01-01T00:00:00.000500001Z&quot;,
    &quot;1969-12-31T23:59:59.999515625Z&quot;,
    &quot;1969-12-31T23:59:59.999015625Z&quot;,
  ]
  .map(str =&gt; {
    const tv = Date.parse(str);
    return `${str} =&gt; ${(new Date(str)).toISOString()} (${Object.is(tv, -0) ? &quot;-0&quot; : tv} ms from epoch)`;
  })
  .join(&quot;\n&quot;)
&apos;
#### ChakraCore, engine262, GraalJS, Hermes, SpiderMonkey, V8
1970-01-01T00:00:00.000500001Z =&gt; 1970-01-01T00:00:00.000Z (0 ms from epoch)
1969-12-31T23:59:59.999515625Z =&gt; 1969-12-31T23:59:59.999Z (-1 ms from epoch)
1969-12-31T23:59:59.999015625Z =&gt; 1969-12-31T23:59:59.999Z (-1 ms from epoch)

#### JavaScriptCore
1970-01-01T00:00:00.000500001Z =&gt; 1970-01-01T00:00:00.000Z (0.500001 ms from epoch)
1969-12-31T23:59:59.999515625Z =&gt; 1970-01-01T00:00:00.000Z (-0.484375 ms from epoch)
1969-12-31T23:59:59.999015625Z =&gt; 1970-01-01T00:00:00.000Z (-0.984375 ms from epoch)

#### Moddable XS
1970-01-01T00:00:00.000500001Z =&gt; 1970-01-01T00:00:00.001Z (1 ms from epoch)
1969-12-31T23:59:59.999515625Z =&gt; 1970-01-01T00:00:00.000Z (0 ms from epoch)
1969-12-31T23:59:59.999015625Z =&gt; 1969-12-31T23:59:59.999Z (-1 ms from epoch)
```

And worse, this results in bizarre round-towards-epoch behavior in new Date construction (as seen above).

Any rounding behavior would correct this bug, but I think it would be best to align with the majority of other implementations in specifically rounding time values down (i.e., towards negative infinity), yielding results equivalent to ignoring all digits beyond millisecond precision.


Also reported to test262 for coverage: https://github.com/tc39/test262/issues/3437</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1853307</commentid>
    <comment_count>1</comment_count>
    <who name="Yusuke Suzuki">ysuzuki</who>
    <bug_when>2022-03-21 13:06:54 -0700</bug_when>
    <thetext>(In reply to Richard Gibson from comment #0)
&gt; JavaScriptCore `Date.parse` can return non-integer non-NaN numbers, in
&gt; violation of
&gt; https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-date.parse
&gt; (which requires the output to be a _time value_—&quot;either a finite **integral
&gt; Number** representing an instant in time to millisecond precision or NaN
&gt; representing no specific instant&quot; [cf.
&gt; https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-time-values-and-
&gt; time-range ]):
&gt; ```sh
&gt; $ eshost -se &apos;
&gt;   [
&gt;     &quot;1970-01-01T00:00:00.000500001Z&quot;,
&gt;     &quot;1969-12-31T23:59:59.999515625Z&quot;,
&gt;     &quot;1969-12-31T23:59:59.999015625Z&quot;,
&gt;   ]
&gt;   .map(str =&gt; {
&gt;     const tv = Date.parse(str);
&gt;     return `${str} =&gt; ${(new Date(str)).toISOString()} (${Object.is(tv, -0)
&gt; ? &quot;-0&quot; : tv} ms from epoch)`;
&gt;   })
&gt;   .join(&quot;\n&quot;)
&gt; &apos;
&gt; #### ChakraCore, engine262, GraalJS, Hermes, SpiderMonkey, V8
&gt; 1970-01-01T00:00:00.000500001Z =&gt; 1970-01-01T00:00:00.000Z (0 ms from epoch)
&gt; 1969-12-31T23:59:59.999515625Z =&gt; 1969-12-31T23:59:59.999Z (-1 ms from epoch)
&gt; 1969-12-31T23:59:59.999015625Z =&gt; 1969-12-31T23:59:59.999Z (-1 ms from epoch)

I think this looks very strange: if we perform TimeClip operation (https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-timeclip),
then all results should be 0 ms since TimeClip is effectively trunc operation.

I think the reasonable behavior is +0 for all three inputs.

&gt; 
&gt; #### JavaScriptCore
&gt; 1970-01-01T00:00:00.000500001Z =&gt; 1970-01-01T00:00:00.000Z (0.500001 ms from
&gt; epoch)
&gt; 1969-12-31T23:59:59.999515625Z =&gt; 1970-01-01T00:00:00.000Z (-0.484375 ms
&gt; from epoch)
&gt; 1969-12-31T23:59:59.999015625Z =&gt; 1970-01-01T00:00:00.000Z (-0.984375 ms
&gt; from epoch)
&gt; 
&gt; #### Moddable XS
&gt; 1970-01-01T00:00:00.000500001Z =&gt; 1970-01-01T00:00:00.001Z (1 ms from epoch)
&gt; 1969-12-31T23:59:59.999515625Z =&gt; 1970-01-01T00:00:00.000Z (0 ms from epoch)
&gt; 1969-12-31T23:59:59.999015625Z =&gt; 1969-12-31T23:59:59.999Z (-1 ms from epoch)
&gt; ```
&gt; 
&gt; And worse, this results in bizarre round-towards-epoch behavior in new Date
&gt; construction (as seen above).

I think this is the right behavior. TimeClip is trunc.
Let&apos;s see

`new Date(-0.484375).valueOf()` =&gt; 0 in all engines.

&gt; 
&gt; Any rounding behavior would correct this bug, but I think it would be best
&gt; to align with the majority of other implementations in specifically rounding
&gt; time values down (i.e., towards negative infinity), yielding results
&gt; equivalent to ignoring all digits beyond millisecond precision.
&gt; 
&gt; 
&gt; Also reported to test262 for coverage:
&gt; https://github.com/tc39/test262/issues/3437</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1853308</commentid>
    <comment_count>2</comment_count>
    <who name="Radar WebKit Bug Importer">webkit-bug-importer</who>
    <bug_when>2022-03-21 13:07:05 -0700</bug_when>
    <thetext>&lt;rdar://problem/90587492&gt;</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1853318</commentid>
    <comment_count>3</comment_count>
      <attachid>455269</attachid>
    <who name="Yusuke Suzuki">ysuzuki</who>
    <bug_when>2022-03-21 13:28:46 -0700</bug_when>
    <thetext>Created attachment 455269
Patch</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1853518</commentid>
    <comment_count>4</comment_count>
    <who name="EWS">ews-feeder</who>
    <bug_when>2022-03-21 21:27:41 -0700</bug_when>
    <thetext>Committed r291603 (248696@main): &lt;https://commits.webkit.org/248696@main&gt;

All reviewed patches have been landed. Closing bug and clearing flags on attachment 455269.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1854245</commentid>
    <comment_count>5</comment_count>
    <who name="Richard Gibson">richard.gibson</who>
    <bug_when>2022-03-23 10:18:48 -0700</bug_when>
    <thetext>(In reply to Yusuke Suzuki from comment #1)
&gt; (In reply to Richard Gibson from comment #0)
&gt; &gt; #### ChakraCore, engine262, GraalJS, Hermes, SpiderMonkey, V8
&gt; &gt; 1970-01-01T00:00:00.000500001Z =&gt; 1970-01-01T00:00:00.000Z (0 ms from epoch)
&gt; &gt; 1969-12-31T23:59:59.999515625Z =&gt; 1969-12-31T23:59:59.999Z (-1 ms from epoch)
&gt; &gt; 1969-12-31T23:59:59.999015625Z =&gt; 1969-12-31T23:59:59.999Z (-1 ms from epoch)
&gt; 
&gt; I think this looks very strange: if we perform TimeClip operation
&gt; (https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-timeclip),
&gt; then all results should be 0 ms since TimeClip is effectively trunc
&gt; operation.
&gt; 
&gt; I think the reasonable behavior is +0 for all three inputs.

I disagree, because privileging January 1 1970 as an attractor isn&apos;t helpful—its status as the epoch is a curiosity of internal representation by computers, and the rest of the world would be justified in expecting that 1970-01-01T00:00:00.000500001Z rounds to milliseconds in the same direction as 1969-12-31T00:00:00.000500001Z.

&gt; &gt; 
&gt; &gt; #### JavaScriptCore
&gt; &gt; 1970-01-01T00:00:00.000500001Z =&gt; 1970-01-01T00:00:00.000Z (0.500001 ms from
&gt; &gt; epoch)
&gt; &gt; 1969-12-31T23:59:59.999515625Z =&gt; 1970-01-01T00:00:00.000Z (-0.484375 ms
&gt; &gt; from epoch)
&gt; &gt; 1969-12-31T23:59:59.999015625Z =&gt; 1970-01-01T00:00:00.000Z (-0.984375 ms
&gt; &gt; from epoch)
&gt; &gt; 
&gt; &gt; #### Moddable XS
&gt; &gt; 1970-01-01T00:00:00.000500001Z =&gt; 1970-01-01T00:00:00.001Z (1 ms from epoch)
&gt; &gt; 1969-12-31T23:59:59.999515625Z =&gt; 1970-01-01T00:00:00.000Z (0 ms from epoch)
&gt; &gt; 1969-12-31T23:59:59.999015625Z =&gt; 1969-12-31T23:59:59.999Z (-1 ms from epoch)
&gt; &gt; ```
&gt; &gt; 
&gt; &gt; And worse, this results in bizarre round-towards-epoch behavior in new Date
&gt; &gt; construction (as seen above).
&gt; 
&gt; I think this is the right behavior. TimeClip is trunc.
&gt; Let&apos;s see
&gt; 
&gt; `new Date(-0.484375).valueOf()` =&gt; 0 in all engines.

Date.parse doesn&apos;t depend upon TimeClip, and couldn&apos;t even use that operation until first parsing a number from input. The above expression bypasses Date.parse, and is instead subject only to the usual treatment of non-integer input in JavaScript where integers are needed. Truncating _numbers_ towards zero is expected, while rounding _datetimes_ towards the start of 1970 is surprising, especially when it results in rollover of coarser unit components due to arithmetic carry (e.g., when input like &quot;1969-…&quot; gets mapped to 1970).

To reiterate, every implementation except JSC and XS round down (i.e., towards negative infinity) rather than truncate (i.e., towards zero). XS is [updating to align with the majority](https://github.com/Moddable-OpenSource/moddable/issues/879), and I would recommend that JSC do the same.

But truncation *is* compliant with the underspecified [Date.parse](https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-date.parse), and JSC is free to break from the herd in this way.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1854280</commentid>
    <comment_count>6</comment_count>
    <who name="Yusuke Suzuki">ysuzuki</who>
    <bug_when>2022-03-23 11:15:15 -0700</bug_when>
    <thetext>(In reply to Richard Gibson from comment #5)
&gt; (In reply to Yusuke Suzuki from comment #1)
&gt; &gt; (In reply to Richard Gibson from comment #0)
&gt; &gt; &gt; #### ChakraCore, engine262, GraalJS, Hermes, SpiderMonkey, V8
&gt; &gt; &gt; 1970-01-01T00:00:00.000500001Z =&gt; 1970-01-01T00:00:00.000Z (0 ms from epoch)
&gt; &gt; &gt; 1969-12-31T23:59:59.999515625Z =&gt; 1969-12-31T23:59:59.999Z (-1 ms from epoch)
&gt; &gt; &gt; 1969-12-31T23:59:59.999015625Z =&gt; 1969-12-31T23:59:59.999Z (-1 ms from epoch)
&gt; &gt; 
&gt; &gt; I think this looks very strange: if we perform TimeClip operation
&gt; &gt; (https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-timeclip),
&gt; &gt; then all results should be 0 ms since TimeClip is effectively trunc
&gt; &gt; operation.
&gt; &gt; 
&gt; &gt; I think the reasonable behavior is +0 for all three inputs.
&gt; 
&gt; I disagree, because privileging January 1 1970 as an attractor isn&apos;t
&gt; helpful—its status as the epoch is a curiosity of internal representation by
&gt; computers, and the rest of the world would be justified in expecting that
&gt; 1970-01-01T00:00:00.000500001Z rounds to milliseconds in the same direction
&gt; as 1969-12-31T00:00:00.000500001Z.

I think handling differently in Date.parse is inconsistent. The rest of the spec is consistently using TimeClip, and that is trunc to the epoch.
If it looks strange, then we should change TimeClip first.

&gt; 
&gt; &gt; &gt; 
&gt; &gt; &gt; #### JavaScriptCore
&gt; &gt; &gt; 1970-01-01T00:00:00.000500001Z =&gt; 1970-01-01T00:00:00.000Z (0.500001 ms from
&gt; &gt; &gt; epoch)
&gt; &gt; &gt; 1969-12-31T23:59:59.999515625Z =&gt; 1970-01-01T00:00:00.000Z (-0.484375 ms
&gt; &gt; &gt; from epoch)
&gt; &gt; &gt; 1969-12-31T23:59:59.999015625Z =&gt; 1970-01-01T00:00:00.000Z (-0.984375 ms
&gt; &gt; &gt; from epoch)
&gt; &gt; &gt; 
&gt; &gt; &gt; #### Moddable XS
&gt; &gt; &gt; 1970-01-01T00:00:00.000500001Z =&gt; 1970-01-01T00:00:00.001Z (1 ms from epoch)
&gt; &gt; &gt; 1969-12-31T23:59:59.999515625Z =&gt; 1970-01-01T00:00:00.000Z (0 ms from epoch)
&gt; &gt; &gt; 1969-12-31T23:59:59.999015625Z =&gt; 1969-12-31T23:59:59.999Z (-1 ms from epoch)
&gt; &gt; &gt; ```
&gt; &gt; &gt; 
&gt; &gt; &gt; And worse, this results in bizarre round-towards-epoch behavior in new Date
&gt; &gt; &gt; construction (as seen above).
&gt; &gt; 
&gt; &gt; I think this is the right behavior. TimeClip is trunc.
&gt; &gt; Let&apos;s see
&gt; &gt; 
&gt; &gt; `new Date(-0.484375).valueOf()` =&gt; 0 in all engines.
&gt; 
&gt; Date.parse doesn&apos;t depend upon TimeClip, and couldn&apos;t even use that
&gt; operation until first parsing a number from input. The above expression
&gt; bypasses Date.parse, and is instead subject only to the usual treatment of
&gt; non-integer input in JavaScript where integers are needed. Truncating
&gt; _numbers_ towards zero is expected, while rounding _datetimes_ towards the
&gt; start of 1970 is surprising, especially when it results in rollover of
&gt; coarser unit components due to arithmetic carry (e.g., when input like
&gt; &quot;1969-…&quot; gets mapped to 1970).

I don&apos;t think it is surprising because of how TimeClip is implemented.
TimeClip is not a number function, it is intended to be used only for time value (as the name is specified).
It is used when the input time is including a fraction, and in this Date.parse case, the parser is parsing sub-milliseconds in JSC.
So, after getting an input, performing TimeClip is reasonable as it is used in the other places which take double input.
I think whether we should parse and recognize sub-milliseconds in Date.parse is different question and I think using TimeClip is just correct behavior.

&gt; 
&gt; To reiterate, every implementation except JSC and XS round down (i.e.,
&gt; towards negative infinity) rather than truncate (i.e., towards zero). XS is
&gt; [updating to align with the
&gt; majority](https://github.com/Moddable-OpenSource/moddable/issues/879), and I
&gt; would recommend that JSC do the same.
&gt; 
&gt; But truncation *is* compliant with the underspecified
&gt; [Date.parse](https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-
&gt; date.parse), and JSC is free to break from the herd in this way.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1854365</commentid>
    <comment_count>7</comment_count>
    <who name="Richard Gibson">richard.gibson</who>
    <bug_when>2022-03-23 13:22:37 -0700</bug_when>
    <thetext>Look at *how* TimeClip is used...
* In the Date constructor with a single argument, where the value to be clipped is either (step 4.b) the time value from an existing Date instance, or (step 4.c.ii) a time value output from the Date.parse algorithm, or (step 4.c.iii) the result of interpreting the argument as a number (and note that the first two cases are _already_ fraction-free time values).
* In the Date constructor with more than one argument (step 5), where the value to be clipped is derived from MakeDate&apos;s arithmetic combination of MakeDay output with MakeTime output (both of which are fraction-free, and theirselves derived from truncating the _numeric_ time component arguments).
* In Date.UTC and Date.prototype.set{,UTC}{Date,FullYear,Hours,Milliseconds,Minutes,Month,Seconds} and Date.prototype.setYear, all of which use a MakeDate(…) pattern analogous to the multi-argument Date constructor case.
* In Date.setTime, where the value to be clipped is the result of interpreting the argument as a number.

The only cases where TimeClip input can have a nonempty fractional component are precisely the two in which a date function treats a single argument as a number (`Date(nonDateNumberable)` and `Date.setTime(numberable)`), which are expected to experience truncation towards zero per the usual ToNumber pattern of deriving integers from inputs. In all other cases, the TimeClip input is **already** fraction-free and its primary purpose is replacing high-magnitude Number values (specifically those outside the valid range of time values) with NaN.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1854366</commentid>
    <comment_count>8</comment_count>
    <who name="Richard Gibson">richard.gibson</who>
    <bug_when>2022-03-23 13:23:45 -0700</bug_when>
    <thetext>Correction: &quot;Date.setTime&quot; → &quot;Date.prototype.setTime&quot;</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1854405</commentid>
    <comment_count>9</comment_count>
    <who name="Yusuke Suzuki">ysuzuki</who>
    <bug_when>2022-03-23 14:37:32 -0700</bug_when>
    <thetext>(In reply to Richard Gibson from comment #7)
&gt; The only cases where TimeClip input can have a nonempty fractional component
&gt; are precisely the two in which a date function treats a single argument as a
&gt; number (`Date(nonDateNumberable)` and `Date.setTime(numberable)`), which are
&gt; expected to experience truncation towards zero per the usual ToNumber
&gt; pattern of deriving integers from inputs. In all other cases, the TimeClip
&gt; input is **already** fraction-free and its primary purpose is replacing
&gt; high-magnitude Number values (specifically those outside the valid range of
&gt; time values) with NaN.

This means that,

1. In the other places, it is fraction-free, thus there is no problem between trunc / floor.
2. Some places are getting fractions, and they are always using TimeClip.

I don&apos;t see any other places using floor to the fractions, thus, if we can get the fraction,
using TimeClip sounds consistent.

Can you show me the example which takes fraction and using floor to get time value?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1854468</commentid>
    <comment_count>10</comment_count>
    <who name="Richard Gibson">richard.gibson</who>
    <bug_when>2022-03-23 16:18:27 -0700</bug_when>
    <thetext>(In reply to Yusuke Suzuki from comment #9)
&gt; 1. In the other places, it is fraction-free, thus there is no problem
&gt; between trunc / floor.
&gt; 2. Some places are getting fractions, and they are always using TimeClip.
&gt; 
&gt; I don&apos;t see any other places using floor to the fractions, thus, if we can
&gt; get the fraction,
&gt; using TimeClip sounds consistent.
&gt; 
&gt; Can you show me the example which takes fraction and using floor to get time
&gt; value?

I&apos;m sorry, I don&apos;t understand this. Can you elaborate and/or rephrase?

What I&apos;m saying is that there are precisely two code paths in which TimeClip input is not guaranteed to be fraction-free, and both of those involve a code-accessible function interpreting its input as an integer. There is an overwhelming convention in ECMAScript for such interpretation to use ToIntegerOrInfinity (which coerces with ToNumber, replaces NaN and -0 with 0, preserves infinities, and truncates fractional values towards 0), but there is no corresponding convention for how to parse strings into time values—and in fact there would be no normative consequences if ToIntegerOrInfinity were entirely removed from TimeClip an instead moved to `Date` and `Date.prototype.setTime`:
```patch
@@ -32241,5 +32241,5 @@ TimeClip (
           1. If _time_ is not finite, return *NaN*.
           1. If abs(ℝ(_time_)) &amp;gt; 8.64 &amp;times; 10&lt;sup&gt;15&lt;/sup&gt;, return *NaN*.
-          1. Return 𝔽(! ToIntegerOrInfinity(_time_)).
+          1. Return _time_.
         &lt;/emu-alg&gt;
       &lt;/emu-clause&gt;
@@ -32444,5 +32444,5 @@ &lt;h1&gt;Date ( ..._values_ )&lt;/h1&gt;
                 1. Let _tv_ be the result of parsing _v_ as a date, in exactly the same manner as for the `parse` method (&lt;emu-xref href=&quot;#sec-date.parse&quot;&gt;&lt;/emu-xref&gt;).
               1. Else,
-                1. Let _tv_ be ? ToNumber(_v_).
+                1. Let _tv_ be ? ToIntegerOrInfinity(_v_).
             1. Let _dv_ be TimeClip(_tv_).
           1. Else,
@@ -32875,5 +32875,5 @@ &lt;h1&gt;Date.prototype.setTime ( _time_ )&lt;/h1&gt;
         &lt;emu-alg&gt;
           1. Perform ? thisTimeValue(*this* value).
-          1. Let _t_ be ? ToNumber(_time_).
+          1. Let _t_ be ? ToIntegerOrInfinity(_time_).
           1. Let _v_ be TimeClip(_t_).
           1. Set the [[DateValue]] internal slot of this Date object to _v_.
```

But although there is no convention in the spec for how to parse strings into time values, there *is* a majority convention across implementations—and that is to round excess precision towards negative infinity.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1854487</commentid>
    <comment_count>11</comment_count>
    <who name="Yusuke Suzuki">ysuzuki</who>
    <bug_when>2022-03-23 16:32:06 -0700</bug_when>
    <thetext>(In reply to Richard Gibson from comment #10)
&gt; (In reply to Yusuke Suzuki from comment #9)
&gt; &gt; 1. In the other places, it is fraction-free, thus there is no problem
&gt; &gt; between trunc / floor.
&gt; &gt; 2. Some places are getting fractions, and they are always using TimeClip.
&gt; &gt; 
&gt; &gt; I don&apos;t see any other places using floor to the fractions, thus, if we can
&gt; &gt; get the fraction,
&gt; &gt; using TimeClip sounds consistent.
&gt; &gt; 
&gt; &gt; Can you show me the example which takes fraction and using floor to get time
&gt; &gt; value?
&gt; 
&gt; I&apos;m sorry, I don&apos;t understand this. Can you elaborate and/or rephrase?
&gt; 
&gt; What I&apos;m saying is that there are precisely two code paths in which TimeClip
&gt; input is not guaranteed to be fraction-free, and both of those involve a
&gt; code-accessible function interpreting its input as an integer. There is an
&gt; overwhelming convention in ECMAScript for such interpretation to use
&gt; ToIntegerOrInfinity (which coerces with ToNumber, replaces NaN and -0 with
&gt; 0, preserves infinities, and truncates fractional values towards 0), but
&gt; there is no corresponding convention for how to parse strings into time
&gt; values—and in fact there would be no normative consequences if
&gt; ToIntegerOrInfinity were entirely removed from TimeClip an instead moved to
&gt; `Date` and `Date.prototype.setTime`:
&gt; ```patch
&gt; @@ -32241,5 +32241,5 @@ TimeClip (
&gt;            1. If _time_ is not finite, return *NaN*.
&gt;            1. If abs(ℝ(_time_)) &amp;gt; 8.64 &amp;times; 10&lt;sup&gt;15&lt;/sup&gt;, return
&gt; *NaN*.
&gt; -          1. Return 𝔽(! ToIntegerOrInfinity(_time_)).
&gt; +          1. Return _time_.
&gt;          &lt;/emu-alg&gt;
&gt;        &lt;/emu-clause&gt;
&gt; @@ -32444,5 +32444,5 @@ &lt;h1&gt;Date ( ..._values_ )&lt;/h1&gt;
&gt;                  1. Let _tv_ be the result of parsing _v_ as a date, in
&gt; exactly the same manner as for the `parse` method (&lt;emu-xref
&gt; href=&quot;#sec-date.parse&quot;&gt;&lt;/emu-xref&gt;).
&gt;                1. Else,
&gt; -                1. Let _tv_ be ? ToNumber(_v_).
&gt; +                1. Let _tv_ be ? ToIntegerOrInfinity(_v_).
&gt;              1. Let _dv_ be TimeClip(_tv_).
&gt;            1. Else,
&gt; @@ -32875,5 +32875,5 @@ &lt;h1&gt;Date.prototype.setTime ( _time_ )&lt;/h1&gt;
&gt;          &lt;emu-alg&gt;
&gt;            1. Perform ? thisTimeValue(*this* value).
&gt; -          1. Let _t_ be ? ToNumber(_time_).
&gt; +          1. Let _t_ be ? ToIntegerOrInfinity(_time_).
&gt;            1. Let _v_ be TimeClip(_t_).
&gt;            1. Set the [[DateValue]] internal slot of this Date object to _v_.
&gt; ```
&gt; 
&gt; But although there is no convention in the spec for how to parse strings
&gt; into time values, there *is* a majority convention across
&gt; implementations—and that is to round excess precision towards negative
&gt; infinity.

What I&apos;m saying is that, whenever an input can include fraction, ECMAScript spec is using TimeClip to make it time value.
And if we parse sub-milliseconds (JSC is currently doing), then using TimeClip is consistent and natural way.
And as it is said in https://bugs.webkit.org/show_bug.cgi?id=238050#c6, whether we should recognize sub-milliseconds or ignore them in parsing is yet another thing.</thetext>
  </long_desc>
      
          <attachment
              isobsolete="0"
              ispatch="1"
              isprivate="0"
          >
            <attachid>455269</attachid>
            <date>2022-03-21 13:28:46 -0700</date>
            <delta_ts>2022-03-22 00:38:22 -0700</delta_ts>
            <desc>Patch</desc>
            <filename>bug-238050-20220321132846.patch</filename>
            <type>text/plain</type>
            <size>3371</size>
            <attacher name="Yusuke Suzuki">ysuzuki</attacher>
            
              <data encoding="base64">U3VidmVyc2lvbiBSZXZpc2lvbjogMjkxNTc1CmRpZmYgLS1naXQgYS9Tb3VyY2UvSmF2YVNjcmlw
dENvcmUvQ2hhbmdlTG9nIGIvU291cmNlL0phdmFTY3JpcHRDb3JlL0NoYW5nZUxvZwppbmRleCBh
YTNmZGUzMTAxNGY5MDExZmM4MmQxYjkyNzFkMTlhMGNiZjUwMTNlLi44NzY5NWQ1NWM5NzUyNDE5
MTI1Zjk5MzFiMjRkM2Q0NDA2MjY4NjYzIDEwMDY0NAotLS0gYS9Tb3VyY2UvSmF2YVNjcmlwdENv
cmUvQ2hhbmdlTG9nCisrKyBiL1NvdXJjZS9KYXZhU2NyaXB0Q29yZS9DaGFuZ2VMb2cKQEAgLTEs
MyArMSwxOSBAQAorMjAyMi0wMy0yMSAgWXVzdWtlIFN1enVraSAgPHlzdXp1a2lAYXBwbGUuY29t
PgorCisgICAgICAgIFtKU0NdIENoYW5nZSBEYXRlLnBhcnNlIHRvIHN0b3AgcmV0dXJuaW5nIG51
bWJlcnMgd2l0aCBmcmFjdGlvbmFsIHBhcnQKKyAgICAgICAgaHR0cHM6Ly9idWdzLndlYmtpdC5v
cmcvc2hvd19idWcuY2dpP2lkPTIzODA1MAorCisgICAgICAgIFJldmlld2VkIGJ5IE5PQk9EWSAo
T09QUyEpLgorCisgICAgICAgIERhdGUucGFyc2Ugc2hvdWxkIHJldHVybiBOYU4gb3IgaW50ZWdl
ciBudW1iZXJzWzEsMl0uIFRoaXMgcGF0Y2ggYXBwbGllcyB0aW1lQ2xpcAorICAgICAgICB0byB0
aGUgcmVzdWx0IG9mIERhdGUucGFyc2UgdG8gZW5zdXJlIHRoYXQgdGhlIHJldHVybmVkIHZhbHVl
IGlzIHRpbWUgdmFsdWUuCisKKyAgICAgICAgWzFdOiBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi9t
dWx0aXBhZ2UvbnVtYmVycy1hbmQtZGF0ZXMuaHRtbCNzZWMtZGF0ZS5wYXJzZQorICAgICAgICBb
Ml06IGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyL211bHRpcGFnZS9udW1iZXJzLWFuZC1kYXRlcy5o
dG1sI3NlYy10aW1lLXZhbHVlcy1hbmQtdGltZS1yYW5nZQorCisgICAgICAgICogcnVudGltZS9E
YXRlQ29uc3RydWN0b3IuY3BwOgorICAgICAgICAoSlNDOjpKU0NfREVGSU5FX0hPU1RfRlVOQ1RJ
T04pOgorCiAyMDIyLTAzLTIxICBKb25hdGhhbiBCZWRhcmQgIDxqYmVkYXJkQGFwcGxlLmNvbT4K
IAogICAgICAgICBVbnJldmlld2VkLCByZXZlcnRpbmcgcjI5MTU1OC4KZGlmZiAtLWdpdCBhL1Nv
dXJjZS9KYXZhU2NyaXB0Q29yZS9ydW50aW1lL0RhdGVDb25zdHJ1Y3Rvci5jcHAgYi9Tb3VyY2Uv
SmF2YVNjcmlwdENvcmUvcnVudGltZS9EYXRlQ29uc3RydWN0b3IuY3BwCmluZGV4IDc4ODcwZjRl
YWUyZDkzMWY5MzNjYzBlYjQ0N2FiY2Q3ZGUwNmI4MTIuLmU3MzdiMmZhMzhkYTcwOTljNjEwYWNm
OTc1NGJkZjNkMGE4OTYzODMgMTAwNjQ0Ci0tLSBhL1NvdXJjZS9KYXZhU2NyaXB0Q29yZS9ydW50
aW1lL0RhdGVDb25zdHJ1Y3Rvci5jcHAKKysrIGIvU291cmNlL0phdmFTY3JpcHRDb3JlL3J1bnRp
bWUvRGF0ZUNvbnN0cnVjdG9yLmNwcApAQCAtMTU5LDcgKzE1OSw3IEBAIEpTQ19ERUZJTkVfSE9T
VF9GVU5DVElPTihkYXRlUGFyc2UsIChKU0dsb2JhbE9iamVjdCogZ2xvYmFsT2JqZWN0LCBDYWxs
RnJhbWUqIGNhCiAgICAgYXV0byBzY29wZSA9IERFQ0xBUkVfVEhST1dfU0NPUEUodm0pOwogICAg
IFN0cmluZyBkYXRlU3RyID0gY2FsbEZyYW1lLT5hcmd1bWVudCgwKS50b1dURlN0cmluZyhnbG9i
YWxPYmplY3QpOwogICAgIFJFVFVSTl9JRl9FWENFUFRJT04oc2NvcGUsIGVuY29kZWRKU1ZhbHVl
KCkpOwotICAgIFJFTEVBU0VfQU5EX1JFVFVSTihzY29wZSwgSlNWYWx1ZTo6ZW5jb2RlKGpzTnVt
YmVyKHZtLmRhdGVDYWNoZS5wYXJzZURhdGUoZ2xvYmFsT2JqZWN0LCB2bSwgZGF0ZVN0cikpKSk7
CisgICAgUkVMRUFTRV9BTkRfUkVUVVJOKHNjb3BlLCBKU1ZhbHVlOjplbmNvZGUoanNOdW1iZXIo
dGltZUNsaXAodm0uZGF0ZUNhY2hlLnBhcnNlRGF0ZShnbG9iYWxPYmplY3QsIHZtLCBkYXRlU3Ry
KSkpKSk7CiB9CiAKIEpTVmFsdWUgZGF0ZU5vd0ltcGwoKQpkaWZmIC0tZ2l0IGEvSlNUZXN0cy9D
aGFuZ2VMb2cgYi9KU1Rlc3RzL0NoYW5nZUxvZwppbmRleCAxMDFmZWEwZTEwOGQyZjEyMTIzMDgy
ZDU0NDc0MzBhMmIyNDI4NDkzLi43MWIwZDY4NmIyNzI1YTgxN2E4ZDU5YmZjOTI0M2ViN2VjODVj
ZWFkIDEwMDY0NAotLS0gYS9KU1Rlc3RzL0NoYW5nZUxvZworKysgYi9KU1Rlc3RzL0NoYW5nZUxv
ZwpAQCAtMSwzICsxLDEzIEBACisyMDIyLTAzLTIxICBZdXN1a2UgU3V6dWtpICA8eXN1enVraUBh
cHBsZS5jb20+CisKKyAgICAgICAgW0pTQ10gQ2hhbmdlIERhdGUucGFyc2UgdG8gc3RvcCByZXR1
cm5pbmcgbnVtYmVycyB3aXRoIGZyYWN0aW9uYWwgcGFydAorICAgICAgICBodHRwczovL2J1Z3Mu
d2Via2l0Lm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MjM4MDUwCisKKyAgICAgICAgUmV2aWV3ZWQgYnkg
Tk9CT0RZIChPT1BTISkuCisKKyAgICAgICAgKiBzdHJlc3MvZGF0ZS1wYXJzZS10aW1lY2xpcC5q
czogQWRkZWQuCisgICAgICAgIChzaG91bGRCZSk6CisKIDIwMjItMDMtMDggIE1hcmsgTGFtICA8
bWFyay5sYW1AYXBwbGUuY29tPgogCiAgICAgICAgIFJlbW92ZSBpbnZhbGlkIEFTU0VSVCBpbiBM
b2NhbGVJREJ1aWxkZXI6Om92ZXJyaWRlTGFuZ3VhZ2VTY3JpcHRSZWdpb24oKS4KZGlmZiAtLWdp
dCBhL0pTVGVzdHMvc3RyZXNzL2RhdGUtcGFyc2UtdGltZWNsaXAuanMgYi9KU1Rlc3RzL3N0cmVz
cy9kYXRlLXBhcnNlLXRpbWVjbGlwLmpzCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAw
MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAuLmU4NzM1MzI1ODg2YTgyM2ZhY2Fk
MzM3YTY3NGRiNzNlZWEwZDU4YjIKLS0tIC9kZXYvbnVsbAorKysgYi9KU1Rlc3RzL3N0cmVzcy9k
YXRlLXBhcnNlLXRpbWVjbGlwLmpzCkBAIC0wLDAgKzEsMjIgQEAKK2Z1bmN0aW9uIHNob3VsZEJl
KGFjdHVhbCwgZXhwZWN0ZWQpIHsKKyAgICBpZiAoYWN0dWFsICE9PSBleHBlY3RlZCkKKyAgICAg
ICAgdGhyb3cgbmV3IEVycm9yKCdiYWQgdmFsdWU6ICcgKyBhY3R1YWwpOworfQorCitbCisgICAg
IjE5NzAtMDEtMDFUMDA6MDA6MDAuMDAwNTAwMDAxWiIsCisgICAgIjE5NjktMTItMzFUMjM6NTk6
NTkuOTk5NTE1NjI1WiIsCisgICAgIjE5NjktMTItMzFUMjM6NTk6NTkuOTk5MDE1NjI1WiIsCitd
LmZvckVhY2goc3RyID0+IHsKKyAgICBjb25zdCB0diA9IERhdGUucGFyc2Uoc3RyKTsKKyAgICBz
aG91bGRCZShPYmplY3QuaXModHYsIDApLCB0cnVlKTsKKyAgICBzaG91bGRCZSgobmV3IERhdGUo
c3RyKSkudG9JU09TdHJpbmcoKSwgYDE5NzAtMDEtMDFUMDA6MDA6MDAuMDAwWmApOworfSk7CisK
K1sKKyAgICAwLjUwMDAwMSwKKyAgICAtMC40ODQzNzUsCisgICAgLTAuOTg0Mzc1LAorXS5mb3JF
YWNoKHZhbHVlID0+IHsKKyAgICBzaG91bGRCZShuZXcgRGF0ZSh2YWx1ZSkudmFsdWVPZigpLCAw
KTsKK30pOwo=
</data>
<flag name="commit-queue"
          id="483305"
          type_id="3"
          status="-"
          setter="ews-feeder"
    />
          </attachment>
      

    </bug>

</bugzilla>