fix(reader): 修正按索引跳章因 decodeURIComponent 静默失败 (#747) - #752
Open
chy5301 wants to merge 1 commit into
Open
Conversation
view.goTo 无条件对 target 执行 decodeURIComponent,而该函数会先把参数
ToString:数字 5 变成 "5",对象 { index: 5 } 变成 "[object Object]"。
于是 resolveNavigation 的 typeof target === "number" 分支永远走不到,
最终落到 book.resolveHref 找不到目标,renderer.goTo 读 resolved.index
抛错又被 goTo 自己的 catch 吞掉,只在 console 留下一行 Could not go to。
用户侧表现为「点了没反应,也没有任何报错」。
受影响的是所有按索引跳章的入口:桌面端 FoliateViewer.goToIndex(TTS
章节切换、AI 引用在缺少 CFI 时的兜底、目录 page: 前缀跳转),以及移动端
经 WebView 桥接的 window.goToSection。
改为只对字符串解码,href / CFI 路径行为完全不变。数字 target 本就是这个
库的一等公民——view.js 自己就在 pushState(0) 里存数字,popstate 也是直接
把它交给 resolveNavigation,不经过解码。这一并修好了索引跳转后的前进/
后退:此前存进 history 的是解码后的 "5",回退时同样解析不出来。
移动端 window.goToSection 此前会先自行 resolveNavigation、再把结果对象
交给 goTo,但该对象同样会被解码破坏,所以这个绕过从未生效;它的 try/catch
也永远不会触发,因为 goTo 自己吞掉了异常。现直接把索引交给 goTo。
同步重建 assets/reader/reader.html。
Contributor
Author
|
补充一份桌面端真机验证(Windows / Tauri)。用 Playwright 连 WebView2 的 CDP 驱动真实应用,直接调用 本 PR 分支(已修复),同一时刻三次调用:
字符串形式失败、数字形式成功—— 对照:未含本 PR 的分支, |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #747
问题
按索引跳章静默失败:点了没反应,也没有任何报错。受影响的入口:
FoliateViewer.goToIndex—— TTS 章节切换、AI 引用在缺少 CFI 时的兜底跳转、目录page:前缀跳转window.goToSection—— TTS 上/下一章根因
view.js的goTo无条件解码 target:而
decodeURIComponent会先对参数做 ToString:于是
resolveNavigation的第一个分支typeof target === "number"永远为 false,最终落到book.resolveHref("5")找不到目标 → 返回null→renderer.goTo(null)读resolved.index抛 TypeError → 又被goTo自己的 catch 吞掉,只在 console 留下一行Could not go to 5。改动
只对字符串解码:
href / CFI 路径行为完全不变(它们本来就是字符串,仍然照常解码)。
数字 target 本就是这个库的一等公民,两处佐证:
view.js自己就在history.pushState(0)里存数字resolveNavigation(detail.state),不经过解码,数字能正常命中 number 分支也就是说那句无条件解码与库自身的设计相矛盾。修复顺带解决了索引跳转后的前进/后退 —— 此前存进 history 的是解码后的
"5",回退时同样解析不出来。移动端
window.goToSection一并简化它之前会先自行
resolveNavigation(index)、再把结果对象交给view.goTo:但这个对象同样会被
decodeURIComponent变成"[object Object]",所以这个绕过从未生效;外层try/catch也永远不会触发,因为goTo自己吞掉了异常。现在直接把索引交给已修好的goTo。桌面端
goToIndex传的就是裸数字,无需改动。测试
新增
packages/app-expo/src/screens/reader/section-navigation-contract.test.ts,沿用仓库已有的 contract test 写法:断言解码守卫存在、resolveNavigation的 number 分支仍在、移动端桥接直接传索引,并附一条可执行的根因说明(decodeURIComponent对非字符串的 ToString 行为)。已验证:
pnpm --filter @readany/app-expo test全绿(7 文件 17 测试),并反向验证过——还原改动后新测试会失败pnpm --filter app exec tsc --noEmit通过尚未做真机手测。建议 review 时开 devtools 确认:跳章后 console 不再出现
Could not go to <数字>,同时回归确认搜索结果、脚注、书签/高亮等字符串 CFI/href 跳转不受影响。关于
reader.html产物 diff同 #745 的 PR:产物 diff 中约 94 行不是本次逻辑改动,而是补上
72274af8遗漏的产物同步(那个 merge commit 更新了reader.template.html和paginator.js,却没有同步reader.html,导致该页边距修复目前在移动端实际未生效)。在干净的 main 上只跑一次pnpm run build:reader即可复现这 94 行。两个 PR 都带了这份同步,先合并哪个都行,另一个 rebase 后重跑
build:reader即可。一处相邻的既有问题(本 PR 未处理)
decodeURIComponent这行仍在goTo的try之外,所以它是goTo里唯一会 reject 而非记日志的路径:target 字符串含裸%(例如指向notes/50%.xhtml的文档内链接)时会抛URIError,对不 catch 的调用方(window.goToHref/window.goToCFI、桌面goToIndex)就是一个 unhandled rejection。这与 #747 是不同的问题,触发条件也不同,所以没有纳入本 PR 以保持聚焦。如果希望一并处理,把解码连同
resolveNavigation一起挪进try即可,我可以另开一个 PR。