From 3d39e59c14dc61adc2733a7e1aea3708a0e25ee0 Mon Sep 17 00:00:00 2001 From: "hol\"mo\"fy" Date: Sun, 26 Jul 2026 20:57:02 +0800 Subject: [PATCH] Update bootstrap.js --- crates/obscura-js/js/bootstrap.js | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/crates/obscura-js/js/bootstrap.js b/crates/obscura-js/js/bootstrap.js index 3ef371a..9dddfba 100644 --- a/crates/obscura-js/js/bootstrap.js +++ b/crates/obscura-js/js/bootstrap.js @@ -406,12 +406,24 @@ const _scheduleAfter = (delay, fn) => { else Deno.core.ops.op_sleep(d).then(fn); }; +// Timers accept a string first arg per the HTML spec (e.g. the Aliyun WAF +// `acw_sc__v2` challenge drives `setTimeout('reload(arg2)', 2)`). A string is +// compiled and run in global scope, identical to a real browser; otherwise the +// call silently no-ops and JS-triggered navigations (cookie → reload) never fire. +const _coerceTimerFn = (fn) => { + if (typeof fn === "string") { + try { return new Function(fn); } catch (_) { return null; } + } + return typeof fn === "function" ? fn : null; +}; + globalThis.setTimeout = (fn, delay = 0, ...args) => { - if (typeof fn !== "function") return ++_tid; + const f = _coerceTimerFn(fn); + if (f === null) return ++_tid; const id = ++_tid; _scheduleAfter(delay, () => { if (_clearedTimers.has(id)) return; - try { fn(...args); } catch(e) { console.error("Timer error:", e); } + try { f(...args); } catch(e) { console.error("Timer error:", e); } }); return id; }; @@ -419,12 +431,13 @@ globalThis.setTimeout = (fn, delay = 0, ...args) => { globalThis.clearTimeout = (id) => { _clearedTimers.add(id); }; globalThis.setInterval = (fn, delay = 0, ...args) => { - if (typeof fn !== "function") return ++_tid; + const f = _coerceTimerFn(fn); + if (f === null) return ++_tid; const id = ++_tid; _intervals.add(id); const tick = () => { if (!_intervals.has(id)) return; - try { fn(...args); } catch(e) { console.error("Interval error:", e); } + try { f(...args); } catch(e) { console.error("Interval error:", e); } if (!_intervals.has(id)) return; _scheduleAfter(delay, tick); };