diff --git a/Update.json b/Update.json index 3cc9edb0..7f8f039a 100644 --- a/Update.json +++ b/Update.json @@ -3649,6 +3649,17 @@ } ], "Notes": "修复了 MonochromeUI / NewBootstrap 新界面在深色模式下加载时出现的白色闪烁(FOUC/CLS)问题。" + }, + "3.5.4": { + "UpdateDate": 1785114353055, + "Prerelease": true, + "UpdateContents": [ + { + "PR": 997, + "Description": "fix: pin Monaco to 0.52.2 to stop intermittent editor load failures" + } + ], + "Notes": "修复了提交代码页面上 Monaco 编辑器有时无法加载、退化为纯文本框的问题(Monaco 0.53.0 的上游 bug)。" } } } \ No newline at end of file diff --git a/XMOJ.user.js b/XMOJ.user.js index 9ab9ad5c..fc6781e5 100644 --- a/XMOJ.user.js +++ b/XMOJ.user.js @@ -1,6 +1,6 @@ // ==UserScript== // @name XMOJ -// @version 3.5.3 +// @version 3.5.4 // @description XMOJ增强脚本 // @author @XMOJ-Script-dev, @langningchen and the community // @namespace https://github/langningchen @@ -551,7 +551,11 @@ let _earlyObs = null; })(); const CaptchaSiteKey = "0x4AAAAAAALBT58IhyDViNmv"; -const MonacoCDN = "https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.53.0/min/vs"; +// 0.53.0 leaks its minified helper variables (m, r, o, ...) into the global scope from every +// chunk file, so whichever chunk happens to be evaluated last clobbers the others and the +// editor randomly fails to load (microsoft/monaco-editor#5015). 0.52.2 ships a single bundle +// and is not affected. cdnjs has no fixed release newer than 0.53.0 yet. +const MonacoCDN = "https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.52.2/min/vs"; const AdminUserList = ["zhuchenrui2", "shanwenxiao", "chenlangning", "admin"]; // Pre-declared so that closures defined before the async init block can reference them @@ -751,8 +755,19 @@ let GetUserBadge = async (Username) => { } } }; +let MonacoLoadPromise = null; async function ensureMonaco() { if (typeof monaco !== 'undefined') return; + // Callers can overlap (submit page editor, merge view, freopen snippets). Without this guard + // each of them appends its own loader.js, and the second loader resets the AMD registry while + // the first one is still resolving modules. + if (MonacoLoadPromise === null) { + MonacoLoadPromise = loadMonaco(); + MonacoLoadPromise.catch(() => { MonacoLoadPromise = null; }); + } + return MonacoLoadPromise; +} +async function loadMonaco() { const loaderUrl = MonacoCDN + '/loader.js'; if (typeof require === 'undefined' || typeof require.config === 'undefined') { await new Promise((resolve, reject) => { diff --git a/package.json b/package.json index d94bfece..c0a7cbf0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "xmoj-script", - "version": "3.5.3", + "version": "3.5.4", "description": "an improvement script for xmoj.tech", "main": "AddonScript.js", "scripts": {