nodebb-plugin-ezoic-infinite 1.7.46 → 1.7.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/public/client.js +15 -3
package/package.json
CHANGED
package/public/client.js
CHANGED
|
@@ -39,7 +39,6 @@
|
|
|
39
39
|
const A_SHOWN = 'data-ezoic-shown'; // timestamp dernier showAds ms
|
|
40
40
|
|
|
41
41
|
const EMPTY_CHECK_MS = 20_000; // délai avant collapse d'un wrap vide post-show
|
|
42
|
-
const MIN_PRUNE_AGE_MS = 8_000; // délai de grâce avant pruning (stabilisation DOM)
|
|
43
42
|
const MAX_INSERTS_RUN = 6; // max insertions par appel runCore
|
|
44
43
|
const MAX_INFLIGHT = 4; // max showAds() simultanés
|
|
45
44
|
const SHOW_THROTTLE_MS = 900; // anti-spam showAds() par id
|
|
@@ -88,6 +87,7 @@
|
|
|
88
87
|
pending: [], // ids en attente de slot inflight
|
|
89
88
|
pendingSet: new Set(),
|
|
90
89
|
wrapByKey: new Map(), // anchorKey → wrap DOM node
|
|
90
|
+
recycling: new Set(), // ids en cours de séquence destroy→define→displayMore
|
|
91
91
|
tcfObs: null, // MutationObserver TCF locator
|
|
92
92
|
runQueued: false,
|
|
93
93
|
burstActive: false,
|
|
@@ -112,7 +112,7 @@
|
|
|
112
112
|
// ── Config ─────────────────────────────────────────────────────────────────
|
|
113
113
|
|
|
114
114
|
// Fix #2 : backoff 10s sur échec pour éviter de spammer l'API
|
|
115
|
-
//
|
|
115
|
+
// Fix #3 : _cfgErrorUntil au scope IIFE pour être réinitialisé dans cleanup()
|
|
116
116
|
let _cfgErrorUntil = 0;
|
|
117
117
|
async function fetchConfig() {
|
|
118
118
|
if (S.cfg) return S.cfg;
|
|
@@ -258,6 +258,9 @@
|
|
|
258
258
|
function pickId(poolKey) {
|
|
259
259
|
const pool = S.pools[poolKey];
|
|
260
260
|
if (!pool.length) return null;
|
|
261
|
+
// Fix #2 : early-exit si tous les ids sont déjà montés — évite O(n) inutile
|
|
262
|
+
if (S.mountedIds.size >= pool.length &&
|
|
263
|
+
pool.every(id => S.mountedIds.has(id))) return null;
|
|
261
264
|
for (let t = 0; t < pool.length; t++) {
|
|
262
265
|
const i = S.cursors[poolKey] % pool.length;
|
|
263
266
|
S.cursors[poolKey] = (S.cursors[poolKey] + 1) % pool.length;
|
|
@@ -303,6 +306,9 @@
|
|
|
303
306
|
if (!best) return null;
|
|
304
307
|
const id = parseInt(best.getAttribute(A_WRAPID), 10);
|
|
305
308
|
if (!Number.isFinite(id)) return null;
|
|
309
|
+
// Fix #1 : éviter de recycler un slot dont la séquence Ezoic est en cours
|
|
310
|
+
if (S.recycling.has(id)) return null;
|
|
311
|
+
S.recycling.add(id);
|
|
306
312
|
|
|
307
313
|
const oldKey = best.getAttribute(A_ANCHOR);
|
|
308
314
|
// Neutraliser l'IO sur ce wrap avant déplacement — évite un showAds
|
|
@@ -327,6 +333,7 @@
|
|
|
327
333
|
// si la pub ne charge pas (détection wrap vide).
|
|
328
334
|
const doDisplay = () => {
|
|
329
335
|
try { ez.displayMore([id]); } catch (_) {}
|
|
336
|
+
S.recycling.delete(id); // Fix #1 : séquence terminée
|
|
330
337
|
observePh(id);
|
|
331
338
|
const t = ts();
|
|
332
339
|
try { best.setAttribute(A_SHOWN, String(t)); } catch (_) {}
|
|
@@ -641,6 +648,7 @@
|
|
|
641
648
|
blockedUntil = ts() + 1500;
|
|
642
649
|
mutate(() => document.querySelectorAll(`.${WRAP_CLASS}`).forEach(dropWrap));
|
|
643
650
|
S.cfg = null;
|
|
651
|
+
_cfgErrorUntil = 0; // Fix #3 : réinitialiser le backoff entre les pages
|
|
644
652
|
S.poolsReady = false;
|
|
645
653
|
S.pools = { topics: [], posts: [], categories: [] };
|
|
646
654
|
S.cursors = { topics: 0, posts: 0, categories: 0 };
|
|
@@ -652,6 +660,7 @@
|
|
|
652
660
|
S.pendingSet.clear();
|
|
653
661
|
S.burstActive = false;
|
|
654
662
|
S.runQueued = false;
|
|
663
|
+
S.recycling.clear();
|
|
655
664
|
if (S.domObs) { S.domObs.disconnect(); S.domObs = null; }
|
|
656
665
|
if (S.tcfObs) { S.tcfObs.disconnect(); S.tcfObs = null; }
|
|
657
666
|
}
|
|
@@ -751,7 +760,10 @@
|
|
|
751
760
|
$(window).on('action:ajaxify.end.nbbEzoic', () => {
|
|
752
761
|
S.pageKey = pageKey();
|
|
753
762
|
blockedUntil = 0;
|
|
754
|
-
muteConsole
|
|
763
|
+
// muteConsole et warmNetwork sont idempotents — appelés au boot seulement.
|
|
764
|
+
// ensureTcfLocator doit être rappelé : ajaxify retire l'iframe __tcfapiLocator
|
|
765
|
+
// du DOM à chaque navigation, le CMP lève une erreur postMessage sans elle.
|
|
766
|
+
muteConsole(); ensureTcfLocator();
|
|
755
767
|
patchShowAds(); getIO(); ensureDomObserver(); requestBurst();
|
|
756
768
|
});
|
|
757
769
|
|