UNPKG

chrome-devtools-frontend

Version:
69 lines (57 loc) 2.44 kB
// Copyright 2021 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as RenderCoordinator from '../render_coordinator/render_coordinator.js'; const pendingRenders = new WeakSet<HTMLElement>(); const activeRenders = new WeakSet<HTMLElement>(); const subsequentRender = new WeakMap<HTMLElement, () => void>(); const wrappedCallbacks = new WeakMap<() => void, () => void>(); export async function scheduleRender(component: HTMLElement, callback: () => void): Promise<void> { // If scheduleRender is called when there is already a render scheduled for this // component, store the callback against the renderer for after the current // call has finished. if (activeRenders.has(component)) { subsequentRender.set(component, callback); return; } // If this render was already scheduled but hasn't started yet, just return. if (pendingRenders.has(component)) { return; } pendingRenders.add(component); // Create a wrapper around the callback so that we know that it has moved from // pending to active. When it has completed we remove it from the active renderers. let wrappedCallback = wrappedCallbacks.get(callback); if (!wrappedCallback) { wrappedCallback = async () => { pendingRenders.delete(component); activeRenders.add(component); try { await callback.call(component); } catch (error: unknown) { console.error(`ScheduledRender: rendering ${component.nodeName.toLowerCase()}:`); console.error(error); throw error; } finally { activeRenders.delete(component); } }; // Store it for next time so we aren't creating wrappers unnecessarily. wrappedCallbacks.set(callback, wrappedCallback); } // Track that there is render rendering, wait for it to finish, and stop tracking. await RenderCoordinator.write(wrappedCallback); // If during the render there was another schedule render call, get // the callback and schedule it to happen now. if (subsequentRender.has(component)) { const newCallback = subsequentRender.get(component); subsequentRender.delete(component); if (!newCallback) { return; } void scheduleRender(component, newCallback); } } export function isScheduledRender(component: HTMLElement): boolean { return activeRenders.has(component); }