perf(js): use fast polling for fill detection

Replace MutationObserver with 50ms polling strategy.
AdSense sets data-ad-status very quickly after iframe,
but MutationObserver sometimes has delays.

Max polling: 3s (60 attempts * 50ms)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
FrankZamora
2025-12-10 16:52:06 -06:00
parent ffc22a21ea
commit 88103a774b
2 changed files with 40 additions and 28 deletions

View File

@@ -258,6 +258,15 @@
// DETECCION DE LLENADO
// =========================================================================
/** @type {Map<Element, number>} */
var pollIntervals = new Map();
/** Intervalo de polling rapido en ms */
var POLL_INTERVAL = 50;
/** Maximo de intentos de polling (50ms * 60 = 3 segundos max) */
var MAX_POLL_ATTEMPTS = 60;
/**
* Inicia la deteccion de llenado para un slot
* @param {Element} slot
@@ -269,33 +278,30 @@
return;
}
// Configurar timeout
var timeoutId = setTimeout(function() {
debugLog('Timeout de llenado alcanzado');
markSlotEmpty(slot);
}, CONFIG.fillTimeout);
fillTimeouts.set(slot, timeoutId);
// Estrategia: Polling rapido (50ms) para detectar data-ad-status lo antes posible.
// AdSense establece data-ad-status muy rapido despues de inyectar el iframe,
// pero MutationObserver a veces no lo detecta inmediatamente.
var pollCount = 0;
var pollId = setInterval(function() {
pollCount++;
// Configurar MutationObserver si hay soporte
if (hasMutationObserverSupport()) {
var mutationObserver = new MutationObserver(function(mutations) {
if (checkFillStatus(slot, ins)) {
// Ya procesado en checkFillStatus
}
});
if (checkFillStatus(slot, ins)) {
// Estado detectado, limpiar polling
clearInterval(pollId);
pollIntervals.delete(slot);
return;
}
mutationObserver.observe(ins, {
attributes: true,
childList: true,
subtree: true,
attributeFilter: ['data-ad-status']
});
// Si alcanzamos el maximo de intentos, marcar como vacio
if (pollCount >= MAX_POLL_ATTEMPTS) {
debugLog('Polling timeout alcanzado (' + (pollCount * POLL_INTERVAL) + 'ms)');
clearInterval(pollId);
pollIntervals.delete(slot);
markSlotEmpty(slot);
}
}, POLL_INTERVAL);
fillObservers.set(slot, mutationObserver);
} else {
// Sin MutationObserver, solo usar timeout
debugLog('Sin soporte MutationObserver, usando solo timeout');
}
pollIntervals.set(slot, pollId);
}
/**
@@ -353,17 +359,23 @@
}
/**
* Limpia observadores y timeouts de un slot
* Limpia observadores, timeouts e intervalos de un slot
* @param {Element} slot
*/
function cleanupSlot(slot) {
// Limpiar timeout
// Limpiar polling interval
if (pollIntervals.has(slot)) {
clearInterval(pollIntervals.get(slot));
pollIntervals.delete(slot);
}
// Limpiar timeout (legacy)
if (fillTimeouts.has(slot)) {
clearTimeout(fillTimeouts.get(slot));
fillTimeouts.delete(slot);
}
// Limpiar MutationObserver
// Limpiar MutationObserver (legacy)
if (fillObservers.has(slot)) {
fillObservers.get(slot).disconnect();
fillObservers.delete(slot);

View File

@@ -18,7 +18,7 @@ if (!defined('ABSPATH')) {
}
// Definir constante de versión del tema
define('ROI_VERSION', '1.0.23');
define('ROI_VERSION', '1.0.24');
// =============================================================================
// 1. CARGAR AUTOLOADER MANUAL