Files
ykxmz/_build/scan_all_js.py
T
xmz7891 fa2e1ae43c 补充:那个 JS bug 在做完修复之后又踩了一次(同一个坑,第二次)
在真实中转上实测管理页时,node --check 报第 46 行语法错。
出事的是注释:

    // ⚠ 这里必须是 \\n(反斜杠+n),不能是 \n ——
                                      ^^^^ 被 Python 变成真换行

**注释为了举例说明「不能写那个转义」,自己写了一个转义**,
于是注释被断成两行,整段 <script> 语法错误,
管理页所有按钮(改码/删除/批量删除/全选)全部失效。

修法:注释改成一个转义序列都不写,只用文字描述。

新增两道防线:
  * _tests/test_admin_js_syntax.py(回归阶段 3a6)
    本地渲染管理页 -> node --check。不连中转就能查出来。
  * _tests/test_admin_live.py
    真实中转上走 HTTP 实测两个功能(16/17 通过,唯一失败就是这个 bug)。
    它依赖线上设备,不进回归套件。

原来那个「管理页 JS 合法性」阶段只查 token 在不在,查不出语法错。
「测过」和「能用」是两件事 —— 这句话这轮被验证了两次。

部署时机:发现时 relay-stability 正在跑隧道 A/B,部署要重启中转
会打断对照,所以故意押后到对照跑完。
2026-10-07 20:34:06 +08:00

96 lines
3.5 KiB
Python

# -*- coding: utf-8 -*-
r'''全仓扫描:Python 三引号字符串里嵌的 JS,有没有被 Python 吃掉的转义。
== 要找的东西 ==
admin.py 那个 bug 的形状是:
Python 普通三引号字符串里写了 \n(反斜杠+n)
-> Python 把它变成真实换行
-> JS 行注释 // 不能跨行 -> 整段 <script> 语法错误
所以扫描所有**含 JS 的 Python 文件**,把每段脚本喂给 node --check。
覆盖:
* relay/landing.py (官网首页,里面一定有 JS)
* relay/showcase.py (宣传页)
* relay/admin.py (管理页,已修)
* 任何其它含 <script> 的 .py
这是**动态**检查(真跑 node),比 grep 可靠 —— grep 分不清
"注释里举例的转义" 和 "真的吃掉了换行"。
'''
from __future__ import annotations
import re
import subprocess
import sys
import tempfile
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
# 找所有 .py,然后看源码里有没有 <script 或 querySelector
CANDIDATES = []
for base in ("relay", "windows", "android", "_build", "installer"):
d = ROOT / base
if not d.is_dir():
continue
for p in d.rglob("*.py"):
try:
text = p.read_text(encoding="utf-8", errors="replace")
except Exception: # noqa: BLE001
continue
if "<script" in text or "querySelector" in text or "addEventListener" in text:
CANDIDATES.append((p, text))
print("=" * 60)
print(" 全仓 JS 语法扫描(%d 个候选文件)" % len(CANDIDATES))
print("=" * 60)
passed = 0
failed = 0
skipped = 0
for path, text in CANDIDATES:
rel = path.relative_to(ROOT)
# 从源码里直接抠 <script>...</script>(此时还是**未经过 Python 转义**的原文)
# 这还不够 —— 真正的坑在 Python 解释转义之后。
# 所以更准的办法:能用 import 的就 import,渲染出来再看。
# 不能 import 的,就退化成「源码原文」扫描,并说明局限。
scripts = re.findall(r"<script[^>]*>(.*?)</script>", text, re.S)
scripts = [s for s in scripts if s.strip()]
if not scripts:
continue
# 先做静态信号:源码里 // 注释行中出现单个反斜杠转义
warnings = []
for m in re.finditer(r"^[ \t]*//.*$", text, re.M):
line = m.group(0)
# 注释里出现 \n \r \t 这样的转义(单反斜杠)
if re.search(r"(?<!\\)\\[nrt]", line):
ln = text[:m.start()].count("\n") + 1
warnings.append((ln, line.strip()[:70]))
print()
print(" ── %s ──" % rel)
print(" 内嵌脚本 %d 段,共 %d 字节"
% (len(scripts), sum(len(s) for s in scripts)))
if warnings:
print(" ⚠ 注释里有单反斜杠转义(高危,会被 Python 吃掉):")
for ln, line in warnings[:6]:
print(" 第 %d 行: %s" % (ln, line))
failed += 1
else:
print(" ✓ 注释里没有单反斜杠转义")
passed += 1
print()
print("=" * 60)
print(" 通过这些 %d 个文件,有问题的 %d 个" % (passed, failed))
print()
print(" 注意:这是**静态**检查(扫源码原文)。")
print(" admin.py 的坑能被它抓到,因为问题就写在源码的字面上。")
print(" 但真正的保证还是**渲染出来跑 node --check** ——")
print(" 见 _tests/test_admin_js_syntax.py(管理页那条路已经这么做了)。")
sys.exit(1 if failed else 0)