diff --git a/src/content/deps/amd.ts b/src/content/deps/amd.ts index 5c408fd..1ced3ee 100644 --- a/src/content/deps/amd.ts +++ b/src/content/deps/amd.ts @@ -7,6 +7,22 @@ const originalDefine = amdLite.define; */ const definedModules = new Set(); +/** + * Throttle timer to make sure only one attempt at loading modules will run for a batch of loaded scripts. + */ +let throttledAutoRunTimer: NodeJS.Timeout | number | undefined; + +/** + * Schedule the automatic resolving of all waiting modules on the next available frame. + */ +function scheduleModulesAutoRun() { + clearTimeout(throttledAutoRunTimer); + + throttledAutoRunTimer = setTimeout(() => { + amdLite.resolveDependencies(Object.keys(amdLite.waitingModules)); + }); +} + amdLite.define = (name, dependencies, originalCallback) => { // Chrome doesn't run the same content script multiple times, while Firefox does. Since each content script and their // chunks are intended to be run only once, we should just ignore any attempts of running the same module more than @@ -17,20 +33,21 @@ amdLite.define = (name, dependencies, originalCallback) => { definedModules.add(name); - return originalDefine(name, dependencies, function () { + originalDefine(name, dependencies, function () { const callbackResult = originalCallback(...arguments); // Workaround for the entry script not returning anything causing AMD-Lite to send warning about modules not // being loaded/not existing. return typeof callbackResult !== 'undefined' ? callbackResult : {}; - }) + }); + + // Schedule the auto run on the next available frame. Firefox and Chromium have a lot of differences in how they + // decide to execute content scripts. For example, Firefox might decide to skip a frame before attempting to load + // different groups of them. Chromium on the other hand doesn't have that issue, but it doesn't allow us to, for + // example, schedule a microtask to run the modules. + scheduleModulesAutoRun(); } amdLite.init({ publicScope: window }); - -// We don't have anything asynchronous, so it's safe to execute everything on the next frame. -requestAnimationFrame(() => { - amdLite.resolveDependencies(Object.keys(amdLite.waitingModules)) -});