From 8ea33aeb913cbfb692d4b37ab0224255b0ec0149 Mon Sep 17 00:00:00 2001 From: JianFeeeee Date: Tue, 15 Sep 2026 12:22:15 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B7=A8=E7=AB=AF:=20fix(=E5=A5=97=E4=BB=B6):?= =?UTF-8?q?=20=E6=8A=8A=E8=87=AA=E6=A3=80=204=20=E7=A7=BB=E5=88=B0?= =?UTF-8?q?=E5=88=B0=E6=9C=9F=E9=97=B8=E4=B9=8B=E5=89=8D=EF=BC=8C=E5=B9=B6?= =?UTF-8?q?=E4=BF=AE=E6=8E=89"=E9=94=9A=E7=82=B9=E8=87=AA=E5=8C=B9?= =?UTF-8?q?=E9=85=8D=E5=AF=BC=E8=87=B4=E5=AE=83=E7=A9=BA=E8=BD=AC=E6=8A=A5?= =?UTF-8?q?=20ok"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dsh 报了"移动未完成"(他两次栽在自己的锚点假设上)并把行号级配方留在上一封里。 这一笔把那一步做完,并在做的过程中撞到**移动本身引出的新洞**: 1. 自检 4 从到期闸**下游**移到**上游**(与自检 1/2/3 同层) —— 否则"闸一 exit,自检连跑的机会都没有",而那正是它唯一要防的场景。 `let selfCheckFailed` 的声明一起上移(否则在声明前赋值 → ReferenceError)。 2. ★ 移动后它**空转报 ok**(比原来更糟:连失效都不响)。原因: 锚点写的是 `indexOf('let dueFailed = false;')` / `indexOf('const probeSummary')`, 而**这两串字本身就写在自检代码里**(作为 indexOf 的实参)。自检块一旦移到真闸之前, `indexOf` 第一次命中的就是**自检自己那两行** ⇒ 扫描区间变成自检自己的两行 ⇒ 真闸从没被扫过。 ⇒ 修法:锚点改 `lastIndexOf`(真闸在自检之后),并加一道**自匹配断言** (区间里若出现 `selfSrc.indexOf` 就判红,不许空转)。 实测(pi): - 正常跑:`ok 4 - 到期闸是记账而不是 exit`、汇总照常打; - 变体(把 `process.exit(1)` 塞回 `dueFailed = true;` 之后):**`✗ 套件自检 4`当场打出来** (报文:到期闸区块里又出现了 process.exit())—— 修复前这个变体是 0 命中; - 变体撤销后文件字节恢复(`git diff` 空)。 --- client/electron/test/run-all.mjs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/client/electron/test/run-all.mjs b/client/electron/test/run-all.mjs index 1d70021..c215322 100644 --- a/client/electron/test/run-all.mjs +++ b/client/electron/test/run-all.mjs @@ -551,17 +551,29 @@ let selfCheckFailed = false; */ try { const selfSrc = prose(fileURLToPath(import.meta.url)); - const from = selfSrc.indexOf('let dueFailed = false;'); - const to = selfSrc.indexOf('const probeSummary'); + /* + * ⚠️ 锚点**不许可自匹配**(pi 2026-09-15 实测踩到):原来这两个锚点写的是 + * `'let dueFailed = false;'` / `'const probeSummary'`,而**这两串字本身就出现在下面这段自检代码里**。 + * 把自检块**上移**到到期闸之前以后,`indexOf` 第一次命中的就是**自检自己那两行** ⇒ 扫的区间变成 + * 自检自己的两行 ⇒ 真闸从没被扫过 ⇒ 它**空转报 ok**(比原来更糟:连失效都不响)。 + * 所以:① 锚点取 `lastIndexOf` —— 真闸在这段自检**之后**,而上面两串"标记"必然也出现在自检代码里(作为 indexOf 的实参), + * `indexOf` 会先命中自检自己;`lastIndexOf` 才指向真闸; + * ② 再加一道自匹配断言(见下 `selfSrc.indexOf` 那条),宁可红也不许空转。 + */ + const from = selfSrc.lastIndexOf('const dueStatic = STATIC_ONLY.filter'); + const to = selfSrc.lastIndexOf('const probeSummary = '); + const GATE_MARKERS_OK = from >= 0 && to > from; /* * ⚠️ 必须**先去注释与字符串**再找 `process.exit(`:这条自检自己的报错文案里就有那串字, * 不去掉的话它会**指着自己报红**(我第一次跑就是这样 —— 与 `@ohos`/`toISOString` 那两次同族: * 扫描器咬到自己的文档)。规矩不变:**不靠挪扫描口径解决,靠去掉不该扫的部分**。 */ - const gate = from >= 0 && to > from ? stripComments(selfSrc.slice(from, to)) : ''; + const gate = GATE_MARKERS_OK ? stripComments(selfSrc.slice(from, to)) : ''; const probs = []; if (!gate) { probs.push('找不到到期闸区块(标记被改动)⇒ 这条自检**自己失效**,必须红 —— 不许静默通过'); + } else if (gate.includes('selfSrc.indexOf')) { + probs.push('扫描区间里含**自检自己的代码**(锚点自匹配)⇒ 它只会空转报 ok,必须红'); } else { if (/process\.exit\s*\(/.test(gate)) { probs.push('到期闸区块里又出现了 `process.exit()` ⇒ 它会在汇总之前退出,把汇总与其它红一起吃#掉');