Fix Violentmonkey SyntaxError: wrap async init block in IIFE

Merged
CO
5mo ago
+35-9

Violentmonkey executes userscripts as classic scripts (not ES modules), so the top-level await at line 916 causes a hard SyntaxError, breaking the entire script.

Changes

  • Wrap async init in IIFE: Everything from the login-status fetch through main().then(...) is now inside (async () => { ... })().catch(...), making await valid without requiring module semantics
  • Pre-declare hoisted variables: CurrentUsername, initTheme, and SearchParams are declared at the top level before the IIFE so that closures defined earlier (e.g. PeriodicCloudSync, GetContestProblemList) can still reference them
  • Error surfacing: Added .catch() on the IIFE to log initialization failures to the console
// Before — top-level await; SyntaxError in Violentmonkey
let loginStatus;
await fetch("https://www.xmoj.tech/loginpage.php")
    .then(r => r.text())
    .then(data => (loginStatus = data));

// After — await inside async IIFE
(async () => {
    let loginStatus;
    await fetch("https://www.xmoj.tech/loginpage.php")
        .then(r => r.text())
        .then(data => (loginStatus = data));
    // ... rest of init + main()
})().catch(e => console.error("[XMOJ-Script] Initialization error:", e));

Summary by Sourcery

Wrap the userscript’s asynchronous initialization logic in an async IIFE to avoid top-level await syntax errors in Violentmonkey while preserving access to shared state.

Bug Fixes:

  • Prevent Violentmonkey from throwing a SyntaxError by moving top-level await into an async IIFE-compatible initialization block.

Enhancements:

  • Predeclare shared variables so earlier-defined closures can still access initialization state when moved inside the async IIFE.
  • Log initialization errors from the async IIFE to the console to surface startup failures.