Skip to content

Fix Violentmonkey SyntaxError: wrap async init block in IIFE#986

Merged
PythonSmall-Q merged 7 commits into
devfrom
copilot/fix-syntax-error-in-xmoj-script
May 30, 2026
Merged

Fix Violentmonkey SyntaxError: wrap async init block in IIFE#986
PythonSmall-Q merged 7 commits into
devfrom
copilot/fix-syntax-error-in-xmoj-script

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 30, 2026

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.

Copilot AI linked an issue May 30, 2026 that may be closed by this pull request
2 tasks
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented May 30, 2026

Deploying xmoj-script-dev-channel with  Cloudflare Pages  Cloudflare Pages

Latest commit: e7f94d8
Status: ✅  Deploy successful!
Preview URL: https://a80c1d56.xmoj-script-dev-channel.pages.dev
Branch Preview URL: https://copilot-fix-syntax-error-in.xmoj-script-dev-channel.pages.dev

View logs

Copilot AI changed the title [WIP] Fix syntax error in XMOJ script for Violentmonkey Fix Violentmonkey SyntaxError: wrap async init block in IIFE May 30, 2026
Copilot AI requested a review from PythonSmall-Q May 30, 2026 03:47
@PythonSmall-Q PythonSmall-Q marked this pull request as ready for review May 30, 2026 03:54
Copilot AI review requested due to automatic review settings May 30, 2026 03:54
@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented May 30, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Wrap the login/initialization sequence and main() call in an async IIFE to avoid top-level await SyntaxError in Violentmonkey, while preserving access to shared state via pre-declared variables and adding explicit error logging for initialization failures.

Sequence diagram for async IIFE-based initialization and error handling

sequenceDiagram
    actor Violentmonkey
    participant Userscript
    participant AsyncInitIIFE
    participant XmojServer
    participant Console

    Violentmonkey->>Userscript: Load XMOJ.user.js
    Userscript->>AsyncInitIIFE: (async () => { ... })()
    activate AsyncInitIIFE
    AsyncInitIIFE->>XmojServer: fetch(loginpage.php)
    XmojServer-->>AsyncInitIIFE: Response
    AsyncInitIIFE->>AsyncInitIIFE: await fetch(...).then(...)
    AsyncInitIIFE->>Userscript: Set SearchParams, CurrentUsername, initTheme
    AsyncInitIIFE->>Userscript: main()
    Userscript-->>AsyncInitIIFE: Promise resolved
    deactivate AsyncInitIIFE

    rect rgb(255,240,240)
    AsyncInitIIFE--xConsole: console.error("[XMOJ-Script] Initialization error:", e) (on .catch)
    end
Loading

File-Level Changes

Change Details Files
Wrap top-level async initialization and main() entrypoint in an async IIFE so that await is valid in non-module userscript environments (e.g., Violentmonkey).
  • Introduce an async immediately-invoked function expression around the login-status fetch, initialization logic, and main().then(...) call.
  • Move all previously top-level await-based code into the body of the async IIFE to avoid SyntaxError in classic scripts.
  • Attach a .catch(...) handler to the IIFE to surface initialization errors via console.error with a clear prefix.
XMOJ.user.js
Pre-declare shared initialization variables at top level and convert previous local declarations into assignments so earlier closures can still reference them.
  • Add top-level declarations for CurrentUsername, initTheme, and SearchParams before any closures that might capture them.
  • Replace let SearchParams/CurrentUsername/initTheme declarations in the init block with assignments to the pre-declared variables.
  • Ensure theme initialization function remains assignable and used by previously defined helpers.
XMOJ.user.js

Assessment against linked issues

Issue Objective Addressed Explanation
#985 Make the userscript compatible with Violentmonkey by eliminating the top-level await that causes SyntaxError: await is only valid in async functions, async generators and modules.
#985 Preserve existing initialization behavior (login status fetch, URL search params, current username, theme initialization) while adapting it to be Violentmonkey-compatible.

Possibly linked issues

  • #3168: Yes. The PR removes the top-level await causing Violentmonkey’s SyntaxError by wrapping initialization in an async IIFE.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="XMOJ.user.js" line_range="6355-6358" />
<code_context>
 main().then(r => {
     console.log("XMOJ-Script loaded successfully!");
 });
+})().catch(e => {
+    console.error("[XMOJ-Script] Initialization error:", e);
+});
</code_context>
<issue_to_address>
**issue (bug_risk):** The async IIFE’s `.catch` won’t catch errors from `main()`’s async work.

Since `main()` is not awaited, the IIFE completes once the `.then` handler is registered, so any later rejection from `main()` (or its awaits) bypasses the outer `catch`. To centralize async init error handling, you can instead do something like:

```js
try {
  await main();
  console.log("XMOJ-Script loaded successfully!");
} catch (e) {
  console.error("[XMOJ-Script] Initialization error:", e);
}
```

This preserves the success log while ensuring async failures from `main()` are properly caught and logged.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread XMOJ.user.js Outdated
Comment on lines +6355 to +6358
main().then(r => {
console.log("XMOJ-Script loaded successfully!");
});
})().catch(e => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): The async IIFE’s .catch won’t catch errors from main()’s async work.

Since main() is not awaited, the IIFE completes once the .then handler is registered, so any later rejection from main() (or its awaits) bypasses the outer catch. To centralize async init error handling, you can instead do something like:

try {
  await main();
  console.log("XMOJ-Script loaded successfully!");
} catch (e) {
  console.error("[XMOJ-Script] Initialization error:", e);
}

This preserves the success log while ensuring async failures from main() are properly caught and logged.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a Violentmonkey compatibility issue where the userscript was being executed as a classic script (not an ES module), causing a hard SyntaxError due to top-level await. The initialization sequence is moved into an async IIFE, and a top-level .catch(...) is added to surface init failures.

Changes:

  • Wrapped the async initialization flow (login-status fetch through main()) in an async IIFE to eliminate top-level await.
  • Pre-declared CurrentUsername, initTheme, and SearchParams at top-level so earlier-defined closures can still reference them.
  • Added IIFE-level error logging via .catch(...) to help diagnose initialization failures.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread XMOJ.user.js
Comment thread XMOJ.user.js Outdated
Comment thread XMOJ.user.js Outdated
Comment thread XMOJ.user.js
Comment thread XMOJ.user.js Outdated
Comment thread XMOJ.user.js Outdated
@PythonSmall-Q
Copy link
Copy Markdown
Member

Tested. It can work!!!

@hendragon-bot hendragon-bot Bot added user-script This issue or pull request is related to the main user script and removed user-script This issue or pull request is related to the main user script labels May 30, 2026
@github-actions github-actions Bot force-pushed the copilot/fix-syntax-error-in-xmoj-script branch from 3e71520 to 3263752 Compare May 30, 2026 04:55
@github-actions github-actions Bot force-pushed the copilot/fix-syntax-error-in-xmoj-script branch from 3263752 to 3be870f Compare May 30, 2026 04:55
@pull-request-size pull-request-size Bot added size/M and removed size/S labels May 30, 2026
Signed-off-by: Shan Wenxiao <seanoj_noreply@yeah.net>
@hendragon-bot hendragon-bot Bot added the user-script This issue or pull request is related to the main user script label May 30, 2026
@boomzero
Copy link
Copy Markdown
Member

I believe that you may encounter some issues using violentmonkey

@boomzero
Copy link
Copy Markdown
Member

There are a lot of bugs I think

@boomzero
Copy link
Copy Markdown
Member

boomzero commented May 30, 2026

Also you should probably run fmt

@PythonSmall-Q
Copy link
Copy Markdown
Member

I believe that you may encounter some issues using violentmonkey

I've downloaded it and tried somehow, it is still workable though.

As of fmt, next time in another pr maybe

@PythonSmall-Q PythonSmall-Q merged commit 2993f85 into dev May 30, 2026
5 checks passed
@PythonSmall-Q PythonSmall-Q deleted the copilot/fix-syntax-error-in-xmoj-script branch May 30, 2026 07:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/M user-script This issue or pull request is related to the main user script

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] 暴力猴提示语法错误

4 participants