Skip to content

Proposal: Sandbox setImmediate() in jsdom environment #11204

@gaearon

Description

@gaearon

🚀 Feature Proposal

Currently, setTimeout and setInterval are sandboxed in the Jest jsdom environment.
Concretely, the Jest jsdom environment calls window.close() which will clear all timers:

If you want to be sure to shut down a jsdom window, use window.close(), which will terminate all running timers (and also remove any event listeners on the window and document).

However, setImmediate is not sandboxed like this.

The proposal is to sandbox setImmediate in the jsdom environment. Concretely, let’s clear all the pending immediates right after the window.close() call for consistency. This prevents running them at the time that DOM is already torn down, and we're in an invalid state.

To implement this, we would expose a wrapper that tracks the immediate IDs, removes IDs from the set when the immediate runs, and calls the underlying clearImmediate on the whole set when jsdom shuts down.

Motivation and Example

Jest source code explicitly calls this out as "for now it's OK" which signals to me that this was anticipated as a possible problem.

The motivation is that we want to start using setImmediate in more places, but Jest makes it difficult because by the time immediates run, the jsdom environment is already torn down.

This works (setTimeout is effectively ignored after jsdom shutdown):

test('foo', () => {
  setTimeout(() => {
    document.createElement('div');
  }, 0);
});

but this doesn't (setImmediate still runs after jsdom shutdown):

test('foo', () => {
  setImmediate(() => {
    document.createElement('div'); // crash: jsdom is shut down
  });
});

The proposal is to remove this inconsistency.

The proposal only concerns the Jest jsdom environment because it already sandboxes timers, and jsdom environment is useless after teardown. I don't think this is needed in a plain Node environment.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions