mirror of
https://github.com/hanzoai/react.git
synced 2026-09-24 17:02:27 +00:00
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.
104 lines
2.9 KiB
JavaScript
104 lines
2.9 KiB
JavaScript
/**
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @flow
|
|
*/
|
|
|
|
/* global Bun */
|
|
|
|
type BunReadableStreamController = ReadableStreamController & {
|
|
end(): mixed,
|
|
write(data: Chunk | BinaryChunk): void,
|
|
error(error: Error): void,
|
|
flush?: () => void,
|
|
};
|
|
export type Destination = BunReadableStreamController;
|
|
|
|
export type PrecomputedChunk = string;
|
|
export opaque type Chunk = string;
|
|
export type BinaryChunk = $ArrayBufferView;
|
|
|
|
export function scheduleWork(callback: () => void) {
|
|
setTimeout(callback, 0);
|
|
}
|
|
|
|
export function flushBuffered(destination: Destination) {
|
|
// Bun direct streams provide a flush function.
|
|
// If we don't have any more data to send right now.
|
|
// Flush whatever is in the buffer to the wire.
|
|
if (typeof destination.flush === 'function') {
|
|
destination.flush();
|
|
}
|
|
}
|
|
|
|
export function beginWriting(destination: Destination) {}
|
|
|
|
export function writeChunk(
|
|
destination: Destination,
|
|
chunk: PrecomputedChunk | Chunk | BinaryChunk,
|
|
): void {
|
|
if (chunk.length === 0) {
|
|
return;
|
|
}
|
|
|
|
destination.write(chunk);
|
|
}
|
|
|
|
export function writeChunkAndReturn(
|
|
destination: Destination,
|
|
chunk: PrecomputedChunk | Chunk | BinaryChunk,
|
|
): boolean {
|
|
return !!destination.write(chunk);
|
|
}
|
|
|
|
export function completeWriting(destination: Destination) {}
|
|
|
|
export function close(destination: Destination) {
|
|
destination.end();
|
|
}
|
|
|
|
export function stringToChunk(content: string): Chunk {
|
|
return content;
|
|
}
|
|
|
|
export function stringToPrecomputedChunk(content: string): PrecomputedChunk {
|
|
return content;
|
|
}
|
|
|
|
export function typedArrayToBinaryChunk(
|
|
content: $ArrayBufferView,
|
|
): BinaryChunk {
|
|
// TODO: Does this needs to be cloned if it's transferred in enqueue()?
|
|
return content;
|
|
}
|
|
|
|
export function byteLengthOfChunk(chunk: Chunk | PrecomputedChunk): number {
|
|
return Buffer.byteLength(chunk, 'utf8');
|
|
}
|
|
|
|
export function byteLengthOfBinaryChunk(chunk: BinaryChunk): number {
|
|
return chunk.byteLength;
|
|
}
|
|
|
|
export function closeWithError(destination: Destination, error: mixed): void {
|
|
if (typeof destination.error === 'function') {
|
|
// $FlowFixMe[incompatible-call]: This is an Error object or the destination accepts other types.
|
|
destination.error(error);
|
|
} else {
|
|
// Earlier implementations doesn't support this method. In that environment you're
|
|
// supposed to throw from a promise returned but we don't return a promise in our
|
|
// approach. We could fork this implementation but this is environment is an edge
|
|
// case to begin with. It's even less common to run this in an older environment.
|
|
// Even then, this is not where errors are supposed to happen and they get reported
|
|
// to a global callback in addition to this anyway. So it's fine just to close this.
|
|
destination.close();
|
|
}
|
|
}
|
|
|
|
export function createFastHash(input: string): string | number {
|
|
return Bun.hash(input);
|
|
}
|