schedulePerformWorkUntilDeadline

schedulePerformWorkUntilDeadline is the function Scheduler uses to ask the host environment to call performWorkUntilDeadline.

The goal is to continue Scheduler work in a later event cycle without relying on a slow or overly delayed mechanism when a better one is available.

The Implementation

let schedulePerformWorkUntilDeadline;
if (typeof localSetImmediate === "function") {
  schedulePerformWorkUntilDeadline = () => {
    localSetImmediate(performWorkUntilDeadline);
  };
} else if (typeof MessageChannel !== "undefined") {
  const channel = new MessageChannel();
  const port = channel.port2;
  channel.port1.onmessage = performWorkUntilDeadline;
  schedulePerformWorkUntilDeadline = () => {
    port.postMessage(null);
  };
} else {
  schedulePerformWorkUntilDeadline = () => {
    localSetTimeout(performWorkUntilDeadline, 0);
  };
}

Scheduler chooses the available API in this order:

  1. setImmediate
  2. MessageChannel
  3. setTimeout

Why setImmediate First?

When setImmediate exists, Scheduler uses it:

schedulePerformWorkUntilDeadline = () => {
  localSetImmediate(performWorkUntilDeadline);
};

This mainly matters in Node.js and older IE environments. In Node.js, setImmediate also avoids a practical issue with MessageChannel: a MessageChannel can keep the process alive when Scheduler work is not meant to do that.

Why MessageChannel in Browsers?

In browser and worker environments, Scheduler prefers MessageChannel:

const channel = new MessageChannel();
const port = channel.port2;
channel.port1.onmessage = performWorkUntilDeadline;
schedulePerformWorkUntilDeadline = () => {
  port.postMessage(null);
};

Calling port.postMessage(null) schedules a message event. When that message is delivered, channel.port1.onmessage runs performWorkUntilDeadline.

Scheduler prefers this over repeated setTimeout(..., 0) calls because browsers can clamp nested timers, commonly making them wait at least a few milliseconds. That delay is too expensive when Scheduler is repeatedly breaking work into small chunks.

Why Keep setTimeout?

setTimeout is the fallback:

schedulePerformWorkUntilDeadline = () => {
  localSetTimeout(performWorkUntilDeadline, 0);
};

It is not the preferred mechanism, but it is widely available. If neither setImmediate nor MessageChannel exists, Scheduler can still function.

Local References

The code stores local references to native APIs:

const localSetTimeout = setTimeout;
const localClearTimeout = clearTimeout;
const localSetImmediate =
  typeof setImmediate !== "undefined" ? setImmediate : null;

This protects Scheduler from later changes to global APIs, such as test environments or polyfills replacing setTimeout.

Summary

schedulePerformWorkUntilDeadline does not perform Scheduler work itself. It schedules performWorkUntilDeadline using the best available host API. That scheduled callback is what starts one slice of Scheduler execution.