6

With the latest JSDOM (11.6.0), I get an infinite loop when used with Sinon's fake timers.

const sinon = require('sinon');

sinon.useFakeTimers();
require('jsdom'); // This line creates an infinite loop

How can I avoid this infinite loop?

2 Answers 2

7

This is caused by the new Performance API.

The implementation uses Date.now() to calibrate the clock. This is the function:

// This function assumes the clock is accurate.
function calculateClockOffset() {
  const start = Date.now();
  let cur = start;
  while (cur === start) {
    cur = Date.now();
  }
  ...
}

(source, note this code is not in JSDOM but in one of its dependencies, w3c-hr-time)

When you run sinon.useFakeTimers();, it will mock Date.now() to always return the same value, therefore the above code creates an infinite loop.

The workaround is to not mock Date, only setTimeout/setInterval functions:

// Sinon 2.x
sinon.useFakeTimers('setTimeout', 'clearTimeout', 'setInterval', 'clearInterval');

// Sinon 3.x or higher
sinon.useFakeTimers({toFake:['setTimeout', 'clearTimeout', 'setInterval', 'clearInterval']});
Sign up to request clarification or add additional context in comments.

I've used JSDOM and Sinon for years but never managed to hit this specific issue. Nice find!
w3c-hr-time has been changed to bail out after 1e6 iterations, so this should no longer generate an infinite loop (but still a significant and annoying delay, I guess)
0

I found another simple workaround, which may be useful if you have to mock Date: mock Date after creating the JSDOM object.

Comments

Your Answer

Draft saved
Draft discarded

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.