react/scripts/jest/patchMessageChannel.js
Josh Story b526a0a419
[Flight][Fizz] schedule work async (#29551)
While most builds of Flight and Fizz schedule work in new tasks some do
execute work synchronously. While this is necessary for legacy APIs like
renderToString for modern APIs there really isn't a great reason to do
this synchronously.

We could schedule works as microtasks but we actually want to yield so
the runtime can run events and other things that will unblock additional
work before starting the next work loop.

This change updates all non-legacy uses to be async using the best
availalble macrotask scheduler.

Browser now uses postMessage
Bun uses setTimeout because while it also supports setImmediate the
scheduling is not as eager as the same API in node
the FB build also uses setTimeout

This change required a number of changes to tests which were utilizing
the sync nature of work in the Browser builds to avoid having to manage
timers and tasks. I added a patch to install MessageChannel which is
required by the browser builds and made this patched version integrate
with the Scheduler mock. This way we can effectively use `act` to flush
flight and fizz work similar to how we do this on the client.
2024-06-06 10:07:24 -07:00

31 lines
908 B
JavaScript

'use strict';
export function patchMessageChannel(Scheduler) {
global.MessageChannel = class {
constructor() {
const port1 = {
onmesssage: () => {},
};
this.port1 = port1;
this.port2 = {
postMessage(msg) {
if (Scheduler) {
Scheduler.unstable_scheduleCallback(
Scheduler.unstable_NormalPriority,
() => {
port1.onmessage(msg);
}
);
} else {
throw new Error(
'MessageChannel patch was used without providing a Scheduler implementation. This is useful for tests that require this class to exist but are not actually utilizing the MessageChannel class. However it appears some test is trying to use this class so you should pass a Scheduler implemenation to the patch method'
);
}
},
};
}
};
}