UNPKG

phaser-jsx

Version:
115 lines 3.84 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getRenderContext = getRenderContext; exports.setRenderContext = setRenderContext; exports.createRenderContext = createRenderContext; exports.resetRenderContext = resetRenderContext; const reconcile_1 = require("../render/reconcile"); let _context = null; function getRenderContext() { _context !== null && _context !== void 0 ? _context : (_context = createRenderContext()); return _context; } function setRenderContext(context) { _context = context; } function createRenderContext(element = null, scene = null, componentFn = null, componentProps = null) { const state = new Map(); const effects = new Map(); const pendingEffects = []; let stateIndex = 0; let effectIndex = 0; let gameObjectTree = null; let isRendering = false; let needsEffectFlush = false; function flushEffects() { if (isRendering) { needsEffectFlush = true; return; } isRendering = true; needsEffectFlush = false; try { for (const { key, callback, deps } of pendingEffects) { const prev = effects.get(key); const shouldRun = !prev || deps === undefined || !areDepsEqual(prev.deps, deps); if (shouldRun) { if (typeof (prev === null || prev === void 0 ? void 0 : prev.cleanup) === 'function') { prev.cleanup(); } const cleanup = callback(); effects.set(key, { deps, cleanup }); } } pendingEffects.length = 0; effectIndex = 0; } finally { isRendering = false; // If effects were queued during effect execution, flush them if (needsEffectFlush && pendingEffects.length > 0) { // Use setTimeout to break the synchronous cycle setTimeout(flushEffects); } } } const context = { state, effects, pendingEffects, scene, componentFn, componentProps, gameObjectTree, getNextStateIndex: () => stateIndex++, resetStateIndex: () => { stateIndex = 0; }, getNextEffectIndex: () => effectIndex++, resetEffectIndex: () => { effectIndex = 0; }, flushEffects, rerender: () => { setRenderContext(context); stateIndex = 0; effectIndex = 0; if (componentFn && componentProps && scene) { const newElement = componentFn(componentProps); gameObjectTree = (0, reconcile_1.reconcileTree)(newElement, gameObjectTree, scene); } else if (element && scene) { gameObjectTree = (0, reconcile_1.reconcileTree)(element, gameObjectTree, scene); } // Defer effect flushing to prevent infinite loops setTimeout(flushEffects); }, }; return context; } function resetRenderContext() { if (_context) { _context.effects.forEach(({ cleanup }) => { if (typeof cleanup === 'function') { cleanup(); } }); } _context = null; } function areDepsEqual(prevDeps, nextDeps) { if (prevDeps === undefined || nextDeps === undefined) { return false; } if (prevDeps.length !== nextDeps.length) { return false; } // TODO: refactor to `nextDeps.every((dep, i) => Object.is(dep, prevDeps[i]))` for (let i = 0; i < nextDeps.length; i++) { if (!Object.is(prevDeps[i], nextDeps[i])) { return false; } } return true; } //# sourceMappingURL=context.js.map