Skip to content
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

setTimeout() nesting levels: browsers do not match specification #10386

Open
majaha opened this issue Jun 2, 2024 · 2 comments
Open

setTimeout() nesting levels: browsers do not match specification #10386

majaha opened this issue Jun 2, 2024 · 2 comments

Comments

@majaha
Copy link
Contributor

majaha commented Jun 2, 2024

What is the issue with the HTML Standard?

None of Chrome, Firefox or Safari match the timer initialization steps. In particular, the amount of nesting that is required before the timeout is clamped to 4ms differs.

The issue is demonstrated with this code:

<!DOCTYPE html>
<html>

<head>
</head>

<body>
  <button id="run">Run</button>
  <script>
    let last = 0;
    let id = 0;
    let count = 10;

    function timeout() {
      let now = performance.now();
      console.log(now-last);
      last = now;
      id = setTimeout(timeout, 0);
      if (!count--) {
        clearInterval(id);
      }
    }

    function run() {
      console.log("START");
      count = 10;
      last = performance.now();
      clearInterval(id);
      id = setTimeout(timeout, 0);
    }


    document.querySelector("#run").addEventListener("click", run);

  </script>
</body>

</html>

By a close reading of the spec, you can trace the execution like this:

time: 0
run() 
  log("START")
  setTimeout(timeout) (nesting level: 0, timeout: 0)
time: 0
timeout()
  log(0)
  setTimeout(timeout) (nesting level: 1 timeout: 0)
time: 0
timeout()
  log(0)
  setTimeout(timeout) (nesting level: 2 timeout: 0)
time: 0
timeout()
  log(0)
  setTimeout(timeout) (nesting level: 3 timeout: 0)
time: 0
timeout()
  log(0)
  setTimeout(timeout) (nesting level: 4 timeout: 0)
time: 0
timeout()
  log(0)
  setTimeout(timeout) (nesting level: 5 timeout: 0)
time: 0
timeout()
  log(0)
  setTimeout(timeout) (nesting level: 6 timeout: 4)
time: 4
timeout()
  log(4)
  setTimeout(timeout) (nesting level: 7 timeout: 4)
...
...

Which means that by the spec, the output should be approximately:

START
0
0
0
0
0
0
4
...
...

with six 0's before the first 4.

However, both Firefox and Chrome print only four 0's before the first 4. And I think Safari prints five 0's.

So step 5 of the spec doesn't match what implementations are actually doing.

@majaha majaha changed the title setTimeout() implementations do not match specification setTimeout() nesting levels: browsers do not match specification Jun 2, 2024
@annevk
Copy link
Member

annevk commented Jun 10, 2024

cc @domenic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

2 participants