From b5f6cac0ef4128aa94376b3847ef9ae03508032f Mon Sep 17 00:00:00 2001 From: JianFeeeee Date: Sun, 4 Oct 2026 08:23:55 +0800 Subject: [PATCH] =?UTF-8?q?fix(plugins):=20ccquota=20=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E9=A6=96=E6=AC=A1=E6=89=93=E5=BC=80=E6=98=AF=E7=A9=BA=E7=9A=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The plugin page rendered nothing until the operator clicked refresh, and even the click handler was never wired — while every unit test was green and the API returned correct numbers. Four separate mistakes stacked here: 1. The script waited on DOMContentLoaded, an event that had already been dispatched by the time the kernel injects a plugin mount. Replaced with pluginAPI.onTabShown (the kernel's own mechanism, fires with the DOM in place) PLUS an immediate call, because onTabShown alone leaves the page blank when the tab is already open at boot. The billing page does both; I had reduced it to one and broke first paint. 2. The re-entry guard flag lived in a closure variable. The tab's DOM is rebuilt on re-entry, so the handler was wired against a node that no longer existed. The flag now lives on the NODE (__ccqWired), which is what makes re-wiring correct. 3. refresh() swallowed its fetch failure and rendered "no sources", so a broken page and an empty account list looked identical. Failures now surface in the header line, including when pluginAPI.call is missing (an old kernel). 4. THE ACTUAL REASON the page stayed blank: there were TWO ccquota plugins. The embed (go:embed plugins/*.lua) version and the on-disk one both loaded, and the UI injected the EMBED copy — 5182 characters, predating every fix — while every edit I made and every hot reload went to the disk copy. The running binary was serving stale plugin code no amount of reloading could fix. Only a rebuild surfaced it, and only measuring the served