const scheduler = new class { constructor() { this._frameID = -1; this._layoutCallbacks = new Set; } // Public get hasScheduledLayoutCallbacks() { return this._frameID !== -1 || this._layoutCallbacks.size > 0; } scheduleLayout(callback) { if (typeof callback !== "function") return; this._layoutCallbacks.add(callback); this._requestFrameIfNeeded(); } unscheduleLayout(callback) { if (typeof callback !== "function") return; this._layoutCallbacks.delete(callback); } flushScheduledLayoutCallbacks() { this._frameDidFire(); } // Private _requestFrameIfNeeded() { if (this._frameID === -1 && this._layoutCallbacks.size > 0) this._frameID = window.requestAnimationFrame(this._frameDidFire.bind(this)); } _frameDidFire() { if (typeof scheduler.frameWillFire === "function") scheduler.frameWillFire(); this._layout(); this._frameID = -1; this._requestFrameIfNeeded(); if (typeof scheduler.frameDidFire === "function") scheduler.frameDidFire(); } _layout() { // Layouts are not re-entrant. const layoutCallbacks = this._layoutCallbacks; this._layoutCallbacks = new Set; for (let callback of layoutCallbacks) callback(); } };