forked from phenom/healer-man
66 lines
1.7 KiB
TypeScript
66 lines
1.7 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { startCappedFrameLoop } from "./cappedFrameLoopRuntime";
|
|
|
|
function createFrameQueue() {
|
|
const callbacks = new Map<number, (timestampMs: number) => void>();
|
|
const cancelled: number[] = [];
|
|
let nextFrame = 1;
|
|
|
|
return {
|
|
callbacks,
|
|
cancelled,
|
|
requestFrame(callback: (timestampMs: number) => void) {
|
|
const frame = nextFrame;
|
|
nextFrame += 1;
|
|
callbacks.set(frame, callback);
|
|
return frame;
|
|
},
|
|
cancelFrame(frame: number) {
|
|
cancelled.push(frame);
|
|
callbacks.delete(frame);
|
|
},
|
|
run(frame: number, timestampMs: number) {
|
|
const callback = callbacks.get(frame);
|
|
callbacks.delete(frame);
|
|
callback?.(timestampMs);
|
|
},
|
|
};
|
|
}
|
|
|
|
describe("capped frame-loop runtime", () => {
|
|
it("starts from Fiber's committed elapsed-seconds clock", () => {
|
|
const queue = createFrameQueue();
|
|
const advances: number[] = [];
|
|
const stop = startCappedFrameLoop({
|
|
targetFps: 30,
|
|
getElapsedSeconds: () => 42,
|
|
advance: (elapsedSeconds) => advances.push(elapsedSeconds),
|
|
requestFrame: queue.requestFrame,
|
|
cancelFrame: queue.cancelFrame,
|
|
});
|
|
|
|
queue.run(1, 1_000);
|
|
queue.run(2, 1_034);
|
|
|
|
expect(advances).toEqual([42, 42.034]);
|
|
stop();
|
|
});
|
|
|
|
it("does not schedule a zombie frame after re-entrant cleanup", () => {
|
|
const queue = createFrameQueue();
|
|
let stop: () => void = () => undefined;
|
|
stop = startCappedFrameLoop({
|
|
targetFps: 60,
|
|
getElapsedSeconds: () => 0,
|
|
advance: () => stop(),
|
|
requestFrame: queue.requestFrame,
|
|
cancelFrame: queue.cancelFrame,
|
|
});
|
|
|
|
queue.run(1, 500);
|
|
|
|
expect(queue.callbacks.size).toBe(0);
|
|
expect(queue.cancelled).toEqual([1]);
|
|
});
|
|
});
|