From de27ecf3275ecd37fb0d6c108a89dc77acb714ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerg=C5=91=20T=C3=B6rcsv=C3=A1ri?= Date: Wed, 5 Aug 2026 20:10:33 +0200 Subject: [PATCH] design-b D-1: bump wxwidgets (gating + legacy twins deleted) + shim cleanup wxwidgets c44c684f7d (D-1c: scheduler lanes unconditional, wxWasmMailboxEnabled gone, fail-fast shim assert) + 24843897e8 (D-1d: startModal / wxWasmRunNestedLoop / popup pump / resolver stacks / bare emscripten_async_call timer entries deleted). pcbjam side of D-1d: the scheduler shim's delivery-tick error path uses wait-registry containment (resolveTopWait nested+modal) instead of the deleted _wxNestedLoopExit stack, and diagnostics.js tracks modal lifecycle via pendingWaits('modal') instead of the deleted Module._endModal hook. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01TEHGiiXMShNXbBr7gSJ7iz --- scripts/common/shims/asyncify-scheduler.js | 9 +++++--- scripts/common/shims/diagnostics.js | 27 ++++++++++------------ wxwidgets | 2 +- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/scripts/common/shims/asyncify-scheduler.js b/scripts/common/shims/asyncify-scheduler.js index 4b18bb0..8dad6a3 100644 --- a/scripts/common/shims/asyncify-scheduler.js +++ b/scripts/common/shims/asyncify-scheduler.js @@ -63,8 +63,11 @@ if (typeof Asyncify !== "undefined" && !globalThis.__wxSchedulerInstalled) { } catch (e) { self._tickArmed = false; if (Module["_wx_dispatch_abandon"]) Module["_wx_dispatch_abandon"](); - var exits = Module["_wxNestedLoopExit"]; - if (exits && exits.length) (exits.pop())(); + // Same containment as the top-level tick's error path (evtloop.cpp): + // a throwing handler must not leave a parked quasi-modal unresolved. + // No-ops when no such wait is open (5101 = wxID_CANCEL). + self.resolveTopWait('nested', 0); + self.resolveTopWait('modal', 5101); throw e; } if (self.mailbox.length > 0) { @@ -158,7 +161,7 @@ if (typeof Asyncify !== "undefined" && !globalThis.__wxSchedulerInstalled) { // pre-resolves the promise — yieldUntil then returns immediately. Per-kind // LIFO stacks give wx modal/nested semantics ("innermost first") without // the legacy per-wait resolver stacks (_wxModalResolvers / - // _wxNestedLoopExit), which die on scheduler builds. Resolution flows + // _wxNestedLoopExit — deleted at doc 20 D-1). Resolution flows // through the S2 deferred-wake law automatically: resolving a wait wakes // its parked sleep via the wrapped handleSleep path. waits: new Map(), // token → {kind, promise, resolve, resolved} diff --git a/scripts/common/shims/diagnostics.js b/scripts/common/shims/diagnostics.js index c67c6a2..18687d2 100644 --- a/scripts/common/shims/diagnostics.js +++ b/scripts/common/shims/diagnostics.js @@ -87,27 +87,24 @@ }; } - // 5. Modal lifecycle (startModal sets Module._endModal; detect appear/disappear). + // 5. Modal lifecycle: poll the scheduler wait registry ("modal" waits). + // (The legacy Module._endModal hook was deleted at doc 20 D-1.) if (typeof Module !== "undefined") { - var seen = false; + var lastModalWaits = 0; setInterval(function() { - if (Module._endModal && !seen) { - seen = true; modalActive = true; - console.log("[DIAG_MODAL] modal started, state=" + asyncState()); - var __origEnd = Module._endModal; - Module._endModal = function(code) { - console.log("[DIAG_MODAL] EndModal code=" + code + " state=" + asyncState()); - modalActive = false; - return __origEnd(code); - }; - } else if (!Module._endModal && seen) { - seen = false; - console.log("[DIAG_MODAL] modal cleanup, state=" + asyncState()); + var S = globalThis.__wxScheduler; + if (!S || typeof S.pendingWaits !== "function") return; + var n = S.pendingWaits("modal"); + if (n !== lastModalWaits) { + console.log("[DIAG_MODAL] modal waits " + lastModalWaits + " -> " + n + + ", state=" + asyncState()); + modalActive = n > 0; + lastModalWaits = n; } }, 100); } - // 6. EM_ASYNC_JS sleeps (startModal, js_enumerateFonts, clipboard, etc.) — log + // 6. EM_ASYNC_JS sleeps (wxWasmYieldUntilJs, js_enumerateFonts, clipboard, etc.) — log // enter/wake so we can see whether an async sleep is NESTED with a fiber swap // at the crash (the #9153 collision). Logging only; delegates unchanged. if (typeof Asyncify !== "undefined" && typeof Asyncify.handleSleep === "function") { diff --git a/wxwidgets b/wxwidgets index a395abd..2484389 160000 --- a/wxwidgets +++ b/wxwidgets @@ -1 +1 @@ -Subproject commit a395abd019b733ba186543ff668a068e461abd96 +Subproject commit 24843897e8f381def1fb3e8ac0d02c3f46fc39bc