denysdovhan / wtfjs

🤪 A list of funny and tricky JavaScript examples
http://bit.ly/wtfjavascript
Do What The F*ck You Want To Public License
34.97k stars 2.55k forks source link

setTimeout with infinity delay will execute function immediately #61

Closed VdustR closed 3 years ago

VdustR commented 7 years ago

It's interesting that passing Infinity as delay parameter while setTimeout() called, the function will executed immediately instead of infinity delay.

setTimeout(() => console.log('called'), Infinity)
initbar commented 7 years ago

@VdustR That's really interesting !! I've ran a few more tests and the results are the same:

screenshot

do you recon the setTimeout implementation automatically sets timeout to zero when something is immeasurable ?

VdustR commented 7 years ago

According to MDN:

Maximum delay value

Browsers including Internet Explorer, Chrome, Safari, and Firefox store the delay as a 32-bit signed integer internally. This causes an integer overflow when using delays larger than 2147483647 (about 24.8 days), resulting in the timeout being executed immediately.

If browsers store it as a 32-bit signed integer then it's not Infinity anymore.

It's explained that setTimeout receive msec as an Interger in MSDN, too:

msec [in]

Type: Integer Integer that specifies the number of milliseconds.

According to Node.js Timer API:

Note: When delay is larger than 2147483647 or less than 1, the delay will be set to 1.

I also found this in w3.org:

6.3 Timers

When the above methods are to get the timeout, they must run the following steps:

  1. Let timeout be the second argument to the method, or zero if the argument was omitted.
  2. Apply the ToString() abstract operation to timeout, and let timeout be the result. [ECMA262]
  3. Apply the ToNumber() abstract operation to timeout, and let timeout be the result. [ECMA262]
  4. If timeout is an Infinity value, a Not-a-Number (NaN) value, or negative, let timeout be zero.
  5. Round timeout down to the nearest integer, and let timeout be the result.
  6. Return timeout.

As point 4 it mentioned, If timeout is an Infinity value, let timeout be zero.

It's seems like there is some difference between these references (minimum is 1 in node.js and 0 in w3.org).

I have no idea if there is a standard or how the browsers or node.js handle this exactly.

I also found this article about the difference between the browsers in this case:

Environment:

OS: Windows 7 Ultimate build 7600 Browsers:

  • IE6
  • IE7
  • IE8
  • Firefox 3.6.9
  • Chrome 7.0.517.5 dev
  • Safari 5.0.2
  • Opera 10.62

Results: Firefox, Chrome and Safari: executed immediately. IE and Opera: never executed

I also tested in some cases:

They are all executed immediately.

github-actions[bot] commented 3 years ago

:tada: This issue has been resolved in version 1.17.0 :tada:

The release is available on:

Your semantic-release bot :package::rocket: