{"version":3,"file":"render-step.mjs","sources":["../../../src/frameloop/render-step.ts"],"sourcesContent":["import { FrameData, Process, Step } from \"./types\"\n\nexport function createRenderStep(runNextFrame: () => void): Step {\n    /**\n     * We create and reuse two queues, one to queue jobs for the current frame\n     * and one for the next. We reuse to avoid triggering GC after x frames.\n     */\n    let thisFrame = new Set<Process>()\n    let nextFrame = new Set<Process>()\n\n    /**\n     * Track whether we're currently processing jobs in this step. This way\n     * we can decide whether to schedule new jobs for this frame or next.\n     */\n    let isProcessing = false\n\n    let flushNextFrame = false\n\n    /**\n     * A set of processes which were marked keepAlive when scheduled.\n     */\n    const toKeepAlive = new WeakSet<Process>()\n\n    let latestFrameData: FrameData = {\n        delta: 0.0,\n        timestamp: 0.0,\n        isProcessing: false,\n    }\n\n    function triggerCallback(callback: Process) {\n        if (toKeepAlive.has(callback)) {\n            step.schedule(callback)\n            runNextFrame()\n        }\n\n        callback(latestFrameData)\n    }\n\n    const step: Step = {\n        /**\n         * Schedule a process to run on the next frame.\n         */\n        schedule: (callback, keepAlive = false, immediate = false) => {\n            const addToCurrentFrame = immediate && isProcessing\n            const queue = addToCurrentFrame ? thisFrame : nextFrame\n\n            if (keepAlive) toKeepAlive.add(callback)\n\n            queue.add(callback)\n\n            return callback\n        },\n\n        /**\n         * Cancel the provided callback from running on the next frame.\n         */\n        cancel: (callback) => {\n            nextFrame.delete(callback)\n            toKeepAlive.delete(callback)\n        },\n\n        /**\n         * Execute all schedule callbacks.\n         */\n        process: (frameData) => {\n            latestFrameData = frameData\n\n            /**\n             * If we're already processing we've probably been triggered by a flushSync\n             * inside an existing process. Instead of executing, mark flushNextFrame\n             * as true and ensure we flush the following frame at the end of this one.\n             */\n            if (isProcessing) {\n                flushNextFrame = true\n                return\n            }\n\n            isProcessing = true\n\n            // Swap this frame and the next to avoid GC\n            const prevFrame = thisFrame\n            thisFrame = nextFrame\n            nextFrame = prevFrame\n\n            // Execute this frame\n            thisFrame.forEach(triggerCallback)\n\n            // Clear the frame so no callbacks remain. This is to avoid\n            // memory leaks should this render step not run for a while.\n            thisFrame.clear()\n\n            isProcessing = false\n\n            if (flushNextFrame) {\n                flushNextFrame = false\n                step.process(frameData)\n            }\n        },\n    }\n\n    return step\n}\n"],"names":[],"mappings":"AAEM,SAAU,gBAAgB,CAAC,YAAwB,EAAA;AACrD;;;AAGG;AACH,IAAA,IAAI,SAAS,GAAG,IAAI,GAAG,EAAW;AAClC,IAAA,IAAI,SAAS,GAAG,IAAI,GAAG,EAAW;AAElC;;;AAGG;IACH,IAAI,YAAY,GAAG,KAAK;IAExB,IAAI,cAAc,GAAG,KAAK;AAE1B;;AAEG;AACH,IAAA,MAAM,WAAW,GAAG,IAAI,OAAO,EAAW;AAE1C,IAAA,IAAI,eAAe,GAAc;AAC7B,QAAA,KAAK,EAAE,GAAG;AACV,QAAA,SAAS,EAAE,GAAG;AACd,QAAA,YAAY,EAAE,KAAK;KACtB;IAED,SAAS,eAAe,CAAC,QAAiB,EAAA;AACtC,QAAA,IAAI,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;AAC3B,YAAA,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;AACvB,YAAA,YAAY,EAAE;QAClB;QAEA,QAAQ,CAAC,eAAe,CAAC;IAC7B;AAEA,IAAA,MAAM,IAAI,GAAS;AACf;;AAEG;AACH,QAAA,QAAQ,EAAE,CAAC,QAAQ,EAAE,SAAS,GAAG,KAAK,EAAE,SAAS,GAAG,KAAK,KAAI;AACzD,YAAA,MAAM,iBAAiB,GAAG,SAAS,IAAI,YAAY;YACnD,MAAM,KAAK,GAAG,iBAAiB,GAAG,SAAS,GAAG,SAAS;AAEvD,YAAA,IAAI,SAAS;AAAE,gBAAA,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC;AAExC,YAAA,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC;AAEnB,YAAA,OAAO,QAAQ;QACnB,CAAC;AAED;;AAEG;AACH,QAAA,MAAM,EAAE,CAAC,QAAQ,KAAI;AACjB,YAAA,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC;AAC1B,YAAA,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC;QAChC,CAAC;AAED;;AAEG;AACH,QAAA,OAAO,EAAE,CAAC,SAAS,KAAI;YACnB,eAAe,GAAG,SAAS;AAE3B;;;;AAIG;YACH,IAAI,YAAY,EAAE;gBACd,cAAc,GAAG,IAAI;gBACrB;YACJ;YAEA,YAAY,GAAG,IAAI;;YAGnB,MAAM,SAAS,GAAG,SAAS;YAC3B,SAAS,GAAG,SAAS;YACrB,SAAS,GAAG,SAAS;;AAGrB,YAAA,SAAS,CAAC,OAAO,CAAC,eAAe,CAAC;;;YAIlC,SAAS,CAAC,KAAK,EAAE;YAEjB,YAAY,GAAG,KAAK;YAEpB,IAAI,cAAc,EAAE;gBAChB,cAAc,GAAG,KAAK;AACtB,gBAAA,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;YAC3B;QACJ,CAAC;KACJ;AAED,IAAA,OAAO,IAAI;AACf;;;;"}