Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions js/activity.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
TENOR, TITLESTRING, Toolbar, Trashcan, TREBLE, Turtles, TURTLESVG,
updatePluginObj, ZERODIVIDEERRORMSG, GRAND_G, GRAND_F,
SHARP, FLAT, buildScale, TREBLE_F, TREBLE_G, GIFAnimator,
MUSICALMODES
MUSICALMODES, waitForReadiness
*/

/*
Expand Down Expand Up @@ -7676,7 +7676,24 @@ define(["domReady!"].concat(MYDEFINES), doc => {
} else {
// Race condition in Firefox: non-AMD scripts might not have
// finished global assignment yet.
setTimeout(initialize, 10);
// Use readiness-based initialization for Firefox for better performance
if (typeof jQuery !== "undefined" && jQuery.browser && jQuery.browser.mozilla) {
waitForReadiness(
() => {
activity.setupDependencies();
activity.domReady(doc);
activity.doContextMenus();
activity.doPluginsAndPaletteCols();
},
{
maxWait: 10000,
minWait: 500,
checkInterval: 100
}
);
} else {
setTimeout(initialize, 10);
}
}
};
initialize();
Expand Down
64 changes: 63 additions & 1 deletion js/utils/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
oneHundredToFraction, prepareMacroExports, preparePluginExports,
processMacroData, processRawPluginData, rationalSum, rgbToHex,
safeSVG, toFixed2, toTitleCase, windowHeight, windowWidth,
fnBrowserDetect
fnBrowserDetect, waitForReadiness
*/

/**
Expand Down Expand Up @@ -343,6 +343,68 @@ function doBrowserCheck() {
jQuery.browser = browser;
}

/**
* Wait for critical dependencies to be ready before calling callback.
* Uses polling with exponential backoff and maximum timeout.
* This replaces the arbitrary 5-second delay for Firefox with actual readiness checks.
*
* @param {Function} callback - The function to call when ready
* @param {Object} options - Configuration options
* @param {number} options.maxWait - Maximum wait time in ms (default: 10000)
* @param {number} options.minWait - Minimum wait time in ms (default: 500)
* @param {number} options.checkInterval - Initial check interval in ms (default: 100)
*/
function waitForReadiness(callback, options = {}) {
const { maxWait = 10000, minWait = 500, checkInterval = 100 } = options;
const startTime = Date.now();

/**
* Check if critical dependencies and DOM elements are ready
* @returns {boolean} True if all critical dependencies are loaded
*/
const isReady = () => {
// Check if critical JavaScript libraries are loaded
const createjsLoaded = typeof createjs !== "undefined" && createjs.Stage;
const howlerLoaded = typeof Howler !== "undefined";
const jqueryLoaded = typeof jQuery !== "undefined";

// Check if critical DOM elements exist
const canvas = document.getElementById("myCanvas");
const loader = document.getElementById("loader");
const toolbars = document.getElementById("toolbars");
const domReady = canvas && loader && toolbars;

return createjsLoaded && howlerLoaded && jqueryLoaded && domReady;
};

/**
* Polling function that checks readiness and calls callback when ready
*/
const check = () => {
const elapsed = Date.now() - startTime;

if (elapsed >= minWait && isReady()) {
// Ready! Initialize the app
// eslint-disable-next-line no-console
console.log(`[Firefox] Initialized in ${elapsed}ms (readiness-based)`);
callback();
} else if (elapsed >= maxWait) {
// Timeout - initialize anyway as fallback
// eslint-disable-next-line no-console
console.warn(
`[Firefox] Initialization timed out after ${maxWait}ms, proceeding anyway`
);
callback();
} else {
// Not ready yet, check again on next animation frame
requestAnimationFrame(check);
}
};

// Start the readiness check loop
requestAnimationFrame(check);
}

// Check for Internet Explorer

window.onload = () => {
Expand Down
Loading